package com.brillilab.service.logic.inventory;

import com.brillilab.common.constant.ResultEnum;
import com.brillilab.common.entity.PageVo;
import com.brillilab.common.exceptions.BrillilabException;
import com.brillilab.domain.enums.kit.KitEnum;
import com.brillilab.service.quartz.BrillQuartzScheduler;
import com.brillilab.common.rocketmq.OnsMessageEnum;
import com.brillilab.common.rocketmq.OnsMessageVo;
import com.brillilab.common.rocketmq.OnsProducer;
import com.brillilab.common.utils.MyBeanUtils;
import com.brillilab.service.utils.QuartzUtils;
import com.brillilab.domain.enums.common.BoolEnum;
import com.brillilab.domain.enums.common.IsDeleteEnum;
import com.brillilab.domain.enums.hardware.LockOperationEnum;
import com.brillilab.domain.enums.inventory.InventoryRecordEnum;
import com.brillilab.domain.enums.inventory.InventoryShareEnum;
import com.brillilab.domain.enums.lab.LabMemberPowerEnum;
import com.brillilab.domain.enums.space.BoxTypeEnum;
import com.brillilab.domain.enums.space.SpaceTypeEnum;
import com.brillilab.domain.po.hardware.HardWareOperateRecord;
import com.brillilab.domain.po.hardware.LockOperation;
import com.brillilab.domain.po.inventory.InventoryDeleteRecord;
import com.brillilab.domain.po.inventory.InventoryRecord;
import com.brillilab.domain.po.inventory.ReagentInventory;
import com.brillilab.domain.po.kit.Kit;
import com.brillilab.domain.po.kit.KitSpec;
import com.brillilab.domain.po.kit.Reagent;
import com.brillilab.domain.po.kit.ReagentType;
import com.brillilab.domain.po.space.*;
import com.brillilab.domain.po.system.Dict;
import com.brillilab.domain.vo.common.KeyValue;
import com.brillilab.domain.vo.inventory.*;
import com.brillilab.domain.vo.kit.*;
import com.brillilab.domain.vo.lab.LabMemberVo;
import com.brillilab.domain.vo.space.BoxGridWithReagentType;
import com.brillilab.domain.vo.space.BoxVo;
import com.brillilab.domain.vo.space.KitBoxVo;
import com.brillilab.domain.vo.user.UserInfoVo;
import com.brillilab.service.constant.JobConstants;
import com.brillilab.service.core.hardware.IHardwareOperateRecordService;
import com.brillilab.service.core.hardware.ILockOperationService;
import com.brillilab.service.core.inventory.IInventoryDeleteRecordService;
import com.brillilab.service.core.inventory.IInventoryRecordService;
import com.brillilab.service.core.inventory.IInventoryShareService;
import com.brillilab.service.core.inventory.IReagentInventoryService;
import com.brillilab.service.core.kit.IKitService;
import com.brillilab.service.core.kit.IKitSpecService;
import com.brillilab.service.core.kit.IReagentService;
import com.brillilab.service.core.kit.IReagentTypeService;
import com.brillilab.service.core.lab.ILabMemberPowerService;
import com.brillilab.service.core.lab.ILabMemberService;
import com.brillilab.service.core.space.IBoxService;
import com.brillilab.service.core.space.IDeviceService;
import com.brillilab.service.core.space.IKitBoxService;
import com.brillilab.service.core.space.IPanelService;
import com.brillilab.service.core.system.IDictService;
import com.brillilab.service.job.inventory.InventoryDeleteJob;
import com.brillilab.service.logic.kit.ReagentLogic;
import com.brillilab.service.logic.kit.SampleLogic;
import com.google.common.base.Splitter;
import org.apache.commons.lang.BooleanUtils;
import org.quartz.JobDataMap;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wuzhiyu
 * @Title: ReagentInventoryLogic
 * @ProjectName brill_lab
 * @Description: TODO
 * @date 2018/11/1913:05
 */
@Service
@Transactional
public class ReagentInventoryLogic {
    @Resource
    private IReagentInventoryService reagentInventoryService;
    @Resource
    private IDictService dictService;
    @Resource
    private IPanelService panelService;
    @Resource
    private IBoxService boxService;
    @Resource
    private IInventoryShareService inventoryShareService;
    @Resource
    private IReagentService reagentService;
    @Resource
    private IKitService kitService;
    @Resource
    private IInventoryRecordService inventoryRecordService;
    @Resource
    private IKitBoxService kitBoxService;
    @Resource
    private IKitSpecService kitSpecService;
    @Resource
    private ILabMemberService labMemberService;
    @Resource
    private ILabMemberPowerService labMemberPowerService;
    @Resource
    private IReagentTypeService reagentTypeService;
    @Resource
    private SampleLogic sampleLogic;
    @Resource
    private ReagentLogic reagentLogic;
    @Resource
    private IDeviceService deviceService;
    @Resource
    private OnsProducer onsProducer;
    @Resource
    private IInventoryDeleteRecordService inventoryDeleteRecordService;
    @Resource
    private IHardwareOperateRecordService hardwareOperateRecordService;
    @Resource
    private ILockOperationService lockOperationService;

    @Resource
    private BrillQuartzScheduler scheduler;

    /**
     * @return java.util.List<com.brillilab.domain.vo.inventory.ReagentPosition>
     * @Description: 获取试剂分组推荐入库位置，一个组合多温区不推荐，多试剂标签不按标签推荐
     * @Params: [group, labId]
     * @author wuzhiyu
     * @date 2018/11/20 9:00
     */
    public List<List<ReagentPosition>> getReagentPositionRecommand(ReagentSpaceGroup group, Long labId, UserInfoVo user) {
        group.setLabMemberId(null);
        if (BooleanUtils.isTrue(group.getIsPrivate())) {
            group.setLabMemberId(user.getLabMemberId());
        }
        List<List<ReagentPosition>> totalList = new ArrayList<>();
        Map<Integer, List<Panel>> panelMap = new HashMap<>();
        Map<Long, List<PanelGridUsed>> panelGridUsedMap = new HashMap<>();
        Map<Integer, List<BoxGridWithReagentType>> gridMap = new HashMap<>();
        boolean needGroupId = true;
        List<Long> groupIdList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(group.getGroupList())) {
            for (ReagentComboGroup one : group.getGroupList()) {
                if (one.getReagentList().size() > 0) {
                    List<Long> groupIds = one.getReagentList().stream().filter(r -> r.getGroupId() != null).map(ReagentCombo::getGroupId).distinct().collect(Collectors.toList());
                    if (groupIds.size() > 0) {
                        groupIdList.addAll(groupIds);
                    }
                }
            }
        }
        if (!CollectionUtils.isEmpty(group.getSingleList())) {
            List<Long> groupIds = group.getSingleList().stream().filter(s -> s.getGroupId() != null).map(ReagentCombo::getGroupId).distinct().collect(Collectors.toList());
            if (groupIds.size() > 0) {
                groupIdList.addAll(groupIds);
            }
        }
        groupIdList = groupIdList.stream().distinct().collect(Collectors.toList());
        if (groupIdList.size() == 1) {
            if (groupIdList.get(0) != null) {
                needGroupId = false;
            }
        }
        Map<Integer, String> zoneMap = dictService.getZoneMap();
        for (int groupCnt = 0; groupCnt < group.getSetCount(); groupCnt++) {
            List<ReagentPosition> positionList = new ArrayList<>();
            totalList.add(positionList);
            Long groupId = null;
            if (needGroupId) {
                groupId = reagentInventoryService.generateInventoryGroupId();
            }
            if (!CollectionUtils.isEmpty(group.getGroupList())) {
                Long newGroupId = groupId;
                group.getGroupList().forEach(g -> {
                    List<ReagentCombo> comList = g.getReagentList();
                    List<ReagentCombo> newReagentComboList = new ArrayList<>();
                    comList.forEach(go -> {
                        ReagentCombo newCombo = new ReagentCombo();
                        MyBeanUtils.copyProperties(go, newCombo);
                        if (newGroupId != null) {
                            newCombo.setGroupId(newGroupId);
                        }
                        newReagentComboList.add(newCombo);
                    });
                    if (comList != null && comList.size() > 0) {
                        //单温区组合推荐位置，否则不推荐
                        if (comList.stream().map(ReagentCombo::getZone).distinct().collect(Collectors.toList()).size() == 1) {
                            Integer zone = comList.get(0).getZone();
                            List<Panel> thisZonePanelList = panelMap.get(zone);
                            if (thisZonePanelList == null) {
                                thisZonePanelList = panelService.getPanelList(labId, zone);
                                panelMap.put(zone, thisZonePanelList);
                            }
                            if (thisZonePanelList != null || thisZonePanelList.size() > 0) {
                                List<Long> reagentTypeList = comList.stream().filter(type -> type.getReagentTypeId() != null).map(ReagentCombo::getReagentId).distinct().collect(Collectors.toList());
                                boolean needFitType = true;
                                if (reagentTypeList.size() == 0 || reagentTypeList.size() > 1) {
                                    needFitType = false;
                                }
                                //Long reagentType = reagentTypeList.get(0);
                                boolean fitSuccess = false;
                                Integer width = g.getWidth();
                                Integer heigth = g.getHeight();
                                if (group.getLabMemberId() != null) {
                                    List<Panel> priPanelLIst = thisZonePanelList.stream().filter(pri -> pri.getLabMemberId() != null && pri.getLabMemberId().equals(group.getLabMemberId())).collect(Collectors.toList());
                                    if (needFitType) {
                                        //to fit reagentTypeId panel
                                        List<Panel> typePanelList = priPanelLIst.stream().filter(type -> {
                                            boolean isFit = false;
                                            if (type.getUserReagentType() != null) {
                                                isFit = type.getUserReagentType().contains(reagentTypeList.get(0).toString());
                                            }
                                            if (type.getSysReagentType() != null && !isFit) {
                                                isFit = type.getSysReagentType().equals(reagentTypeList.get(0));
                                            }
                                            if (type.getSysReagentType() != null && !isFit) {
                                                isFit = type.getSetReagentType().contains(reagentTypeList.get(0).toString());
                                            }
                                            return isFit;
                                        }).collect(Collectors.toList());
                                        if (typePanelList.size() > 0) {
                                            fitSuccess = getFittedPanelGridList(width, heigth, typePanelList, panelGridUsedMap, newReagentComboList, positionList, group.getProductDate(), group.getExpireDate(), group.getBatchNumber(), zoneMap);
                                        }
                                    }
                                    if (!fitSuccess) {
                                        fitSuccess = getFittedPanelGridList(width, heigth, priPanelLIst, panelGridUsedMap, newReagentComboList, positionList, group.getProductDate(), group.getExpireDate(), group.getBatchNumber(), zoneMap);
                                    }
                                }
                                if (!fitSuccess) {
                                    List<Panel> pubPanelLIst = thisZonePanelList.stream().filter(pub -> pub.getLabMemberId() == null).collect(Collectors.toList());
                                    if (needFitType) {
                                        //to fit reagentTypeId panel
                                        List<Panel> typePanelList = pubPanelLIst.stream().filter(type -> {
                                            boolean isFit = false;
                                            if (type.getUserReagentType() != null) {
                                                isFit = type.getUserReagentType().contains(reagentTypeList.get(0).toString());
                                            }
                                            if (type.getSysReagentType() != null && !isFit) {
                                                isFit = type.getSysReagentType().equals(reagentTypeList.get(0));
                                            }
                                            if (type.getSysReagentType() != null && !isFit) {
                                                isFit = type.getSetReagentType().contains(reagentTypeList.get(0).toString());
                                            }
                                            return isFit;
                                        }).collect(Collectors.toList());
                                        if (typePanelList.size() > 0) {
                                            fitSuccess = getFittedPanelGridList(width, heigth, typePanelList, panelGridUsedMap, newReagentComboList, positionList, group.getProductDate(), group.getExpireDate(), group.getBatchNumber(), zoneMap);
                                        }
                                    }
                                    if (!fitSuccess) {
                                        //to fit punlic panel
                                        fitSuccess = getFittedPanelGridList(width, heigth, pubPanelLIst, panelGridUsedMap, newReagentComboList, positionList, group.getProductDate(), group.getExpireDate(), group.getBatchNumber(), zoneMap);
                                    }
                                }
                                if (!fitSuccess) {
                                    // fit failed
                                    ReagentPosition pos = new ReagentPosition();
                                    pos.setHeight(g.getHeight());
                                    pos.setWidth(g.getWidth());
                                    pos.setExpireDate(group.getExpireDate());
                                    pos.setProductDate(group.getProductDate());
                                    pos.setBatchNumber(group.getBatchNumber());
                                    pos.setReagent(newReagentComboList);
                                    positionList.add(pos);
                                }
                            } else {
                                ReagentPosition pos = new ReagentPosition();
                                pos.setHeight(g.getHeight());
                                pos.setWidth(g.getWidth());
                                pos.setExpireDate(group.getExpireDate());
                                pos.setProductDate(group.getProductDate());
                                pos.setBatchNumber(group.getBatchNumber());
                                pos.setReagent(newReagentComboList);
                                positionList.add(pos);
                            }
                        } else {
                            ReagentPosition pos = new ReagentPosition();
                            pos.setHeight(g.getHeight());
                            pos.setWidth(g.getWidth());
                            pos.setExpireDate(group.getExpireDate());
                            pos.setProductDate(group.getProductDate());
                            pos.setBatchNumber(group.getBatchNumber());
                            pos.setReagent(newReagentComboList);
                            positionList.add(pos);
                        }
                    }
                });
            }
            if (!CollectionUtils.isEmpty(group.getSingleList())) {
                List<ReagentCombo> toPanelList = group.getSingleList().stream().filter(o -> {
                    List<KitSpec> specList = kitSpecService.getKitSpecListBySpecId(o.getKitSpecId());
                    KitSpec spec = specList.stream().filter(s -> s.getReagentId().equals(o.getReagentId())).findFirst().get();
                    return !isFitToBoxGrid(spec.getUnit(), spec.getSize());
                }).collect(Collectors.toList());
                List<ReagentCombo> toGridList = group.getSingleList().stream().filter(o -> {
                    List<KitSpec> specList = kitSpecService.getKitSpecListBySpecId(o.getKitSpecId());
                    KitSpec spec = specList.stream().filter(s -> s.getReagentId().equals(o.getReagentId())).findFirst().get();
                    return isFitToBoxGrid(spec.getUnit(), spec.getSize());
                }).collect(Collectors.toList());
                Long newGroupId = groupId;
                if (!CollectionUtils.isEmpty(toPanelList)) {
                    toPanelList.forEach(g -> {
                        ReagentCombo newCombo = new ReagentCombo();
                        MyBeanUtils.copyProperties(g, newCombo);
                        if (newGroupId != null) {
                            newCombo.setGroupId(newGroupId);
                        }
                        List<ReagentCombo> singleOneList = new ArrayList<>();
                        singleOneList.add(newCombo);
                        Integer zone = g.getZone();
                        if (panelMap.get(zone) == null || panelMap.get(zone).size() < 1) {
                            List<Panel> zonePanelList = panelService.getPanelList(labId, zone);
                            panelMap.put(zone, zonePanelList);
                        }
                        List<Panel> thisZonePanelList = panelMap.get(zone);
                        if (thisZonePanelList != null || thisZonePanelList.size() > 0) {
                            Long reagentType = g.getReagentTypeId();
                            boolean fitSuccess = false;
                            Integer width = 1;
                            Integer heigth = 1;
                            if (group.getLabMemberId() != null) {
                                List<Panel> priPanelLIst = thisZonePanelList.stream().filter(pri -> pri.getLabMemberId() != null && pri.getLabMemberId().equals(group.getLabMemberId())).collect(Collectors.toList());
                                if (reagentType != null) {
                                    //to fit reagentTypeId panel
                                    List<Panel> typePanelList = priPanelLIst.stream().filter(type -> {
                                        boolean isFit = false;
                                        if (type.getUserReagentType() != null) {
                                            isFit = type.getUserReagentType().contains(reagentType.toString());
                                        }
                                        if (type.getSysReagentType() != null && !isFit) {
                                            isFit = type.getSysReagentType().equals(reagentType);
                                        }
                                        if (type.getSysReagentType() != null && !isFit) {
                                            isFit = type.getSetReagentType().contains(reagentType.toString());
                                        }
                                        return isFit;
                                    }).collect(Collectors.toList());
                                    if (typePanelList.size() > 0) {
                                        fitSuccess = getFittedPanelGridList(width, heigth, typePanelList, panelGridUsedMap, singleOneList, positionList, group.getProductDate(), group.getExpireDate(), group.getBatchNumber(), zoneMap);
                                    }
                                }
                                if (!fitSuccess) {
                                    fitSuccess = getFittedPanelGridList(width, heigth, priPanelLIst, panelGridUsedMap, singleOneList, positionList, group.getProductDate(), group.getExpireDate(), group.getBatchNumber(), zoneMap);
                                }
                            }
                            if (!fitSuccess) {
                                List<Panel> pubPanelLIst = thisZonePanelList.stream().filter(pri -> pri.getLabMemberId() == null).collect(Collectors.toList());
                                if (reagentType != null) {
                                    {
                                        //to fit reagentTypeId panel
                                        List<Panel> typePanelList = pubPanelLIst.stream().filter(type -> {
                                            boolean isFit = false;
                                            if (type.getUserReagentType() != null) {
                                                isFit = type.getUserReagentType().contains(reagentType.toString());
                                            }
                                            if (type.getSysReagentType() != null && !isFit) {
                                                isFit = type.getSysReagentType().equals(reagentType);
                                            }
                                            if (type.getSysReagentType() != null && !isFit) {
                                                isFit = type.getSetReagentType().contains(reagentType.toString());
                                            }
                                            return isFit;
                                        }).collect(Collectors.toList());
                                        if (typePanelList.size() > 0) {
                                            fitSuccess = getFittedPanelGridList(width, heigth, typePanelList, panelGridUsedMap, singleOneList, positionList, group.getProductDate(), group.getExpireDate(), group.getBatchNumber(), zoneMap);
                                        }
                                    }
                                    if (!fitSuccess) {
                                        //to fit punlic panel
                                        fitSuccess = getFittedPanelGridList(width, heigth, pubPanelLIst, panelGridUsedMap, singleOneList, positionList, group.getProductDate(), group.getExpireDate(), group.getBatchNumber(), zoneMap);
                                    }
                                }
                                if (!fitSuccess) {
                                    // fit failed
                                    ReagentPosition pos = new ReagentPosition();
                                    pos.setWidth(1);
                                    pos.setHeight(1);
                                    pos.setExpireDate(group.getExpireDate());
                                    pos.setProductDate(group.getProductDate());
                                    pos.setBatchNumber(group.getBatchNumber());
                                    pos.setReagent(singleOneList);
                                    positionList.add(pos);
                                }
                            }
                        }
                    });
                }
                if (!CollectionUtils.isEmpty(toGridList)) {
                    toGridList.forEach(g -> {
                        int totalGridCnt = boxService.getBoxGridWithReagentTypeListSpecGtZeroCount(labId, g.getZone());
                        boolean isFitSuccess = false;
                        int fitPassCount = 0;
                        int index = 0;
                        do {
                            List<BoxGridWithReagentType> zoneGridList = gridMap.get(g.getZone());
                            if (zoneGridList == null || (totalGridCnt > 0 && totalGridCnt > zoneGridList.size())) {
                                if (zoneGridList == null) {
                                    zoneGridList = new ArrayList<>();
                                }
                                List<BoxGridWithReagentType> cacheList = boxService.getBoxGridWithReagentTypeListSpecGtZero(labId, g.getZone(), 200, index);
                                zoneGridList.addAll(cacheList);
                                gridMap.put(g.getZone(), zoneGridList);
                            }
                            isFitSuccess = recommendFitGrid(group, zoneMap, positionList, newGroupId, g, zoneGridList);
                            fitPassCount = zoneGridList.size();
                            index = index + 1;
                        } while (!isFitSuccess && fitPassCount < totalGridCnt && (index * 200) < totalGridCnt);
                        if (!isFitSuccess) {
                            ReagentPosition pos = new ReagentPosition();
                            pos.setExpireDate(group.getExpireDate());
                            pos.setProductDate(group.getProductDate());
                            pos.setBatchNumber(group.getBatchNumber());
                            pos.setHeight(1);
                            pos.setWidth(1);
                            List<ReagentCombo> singleOneList = new ArrayList<>();
                            ReagentCombo newCom = new ReagentCombo();
                            BeanUtils.copyProperties(g, newCom);
                            if (newGroupId != null) {
                                newCom.setGroupId(newGroupId);
                            }
                            singleOneList.add(newCom);
                            pos.setReagent(singleOneList);
                            positionList.add(pos);
                        }
                    });
                }
            }
        }
        List<ReagentType> typeList = reagentTypeService.selectLabReagentTypeList(user.getLabId());
        for (List<ReagentPosition> list:totalList){
            for (ReagentPosition position:list){
                for(ReagentCombo combo :position.getReagent()){
                    if(combo.getType().equals(1)){
                        combo.setFirstReagentTypeId(typeList.stream().filter(t->t.getId().equals(combo.getReagentTypeId())).findFirst().get().getParentId());
                    }else{
                        combo.setFirstReagentTypeId(combo.getReagentTypeId());
                    }

                }
            }
        }
        return totalList;
    }

    public boolean recommendFitGrid(ReagentSpaceGroup group, Map<Integer, String> zoneMap, List<ReagentPosition> positionList, Long newGroupId, ReagentCombo g, List<BoxGridWithReagentType> zoneGridList) {
        boolean fitSuccess = false;
        List<BoxGridWithReagentType> notFillList = zoneGridList.stream().filter(f -> f.getIsFill().equals(0)).collect(Collectors.toList());
        BoxGridWithReagentType fittedGrid = null;
        if (group.getLabMemberId() != null) {
            List<BoxGridWithReagentType> priGridList = notFillList.stream().filter(pri -> pri.getLabMemberId() != null && pri.getLabMemberId().equals(group.getLabMemberId())).collect(Collectors.toList());
            if (g.getReagentTypeId() != null) {
                List<BoxGridWithReagentType> typeGridList = priGridList.stream().filter(type -> {
                    boolean isFit = false;
                    if (type.getUserReagentType() != null) {
                        isFit = type.getUserReagentType().contains(g.getReagentTypeId().toString());
                    }
                    if (type.getSysReagentType() != null && !isFit) {
                        isFit = type.getSysReagentType().equals(g.getReagentTypeId());
                    }
                    if (type.getSysReagentType() != null && !isFit) {
                        isFit = type.getSetReagentType().contains(g.getReagentTypeId().toString());
                    }
                    return isFit;
                }).collect(Collectors.toList());
                if (typeGridList.size() > 0) {
                    fitSuccess = true;
                    fittedGrid = typeGridList.get(0);
                    fittedGrid.setIsFill(1);
                }
            }
            if (!fitSuccess) {
                if (priGridList.size() > 0) {
                    fitSuccess = true;
                    fittedGrid = priGridList.get(0);
                    fittedGrid.setIsFill(1);
                }
            }
        }
        if (!fitSuccess) {
            List<BoxGridWithReagentType> pubGridList = notFillList.stream().filter(pub -> pub.getLabMemberId() == null).collect(Collectors.toList());
            if (g.getReagentTypeId() != null) {
                List<BoxGridWithReagentType> typeGridList = pubGridList.stream().filter(type -> {
                    boolean isFit = false;
                    if (type.getUserReagentType() != null) {
                        isFit = type.getUserReagentType().contains(g.getReagentTypeId().toString());
                    }
                    if (type.getSysReagentType() != null && !isFit) {
                        isFit = type.getSysReagentType().equals(g.getReagentTypeId());
                    }
                    if (type.getSysReagentType() != null && !isFit) {
                        isFit = type.getSetReagentType().contains(g.getReagentTypeId().toString());
                    }
                    return isFit;
                }).collect(Collectors.toList());
                if (typeGridList.size() > 0) {
                    fitSuccess = true;
                    fittedGrid = typeGridList.get(0);
                    fittedGrid.setIsFill(1);
                }
            }
            if (!fitSuccess) {
                if (pubGridList.size() > 0) {
                    fitSuccess = true;
                    fittedGrid = pubGridList.get(0);
                    fittedGrid.setIsFill(1);
                }
            }
        }
        if (fitSuccess) {
            ReagentPosition pos = new ReagentPosition();
            pos.setExpireDate(group.getExpireDate());
            pos.setProductDate(group.getProductDate());
            pos.setBatchNumber(group.getBatchNumber());
            pos.setHeight(1);
            pos.setWidth(1);
            List<ReagentCombo> singleOneList = new ArrayList<>();
            ReagentCombo newCom = new ReagentCombo();
            BeanUtils.copyProperties(g, newCom);
            if (newGroupId != null) {
                newCom.setGroupId(newGroupId);
            }
            singleOneList.add(newCom);
            pos.setReagent(singleOneList);
            ReagentInventoryWithOwner inventory = new ReagentInventoryWithOwner();
            inventory.setPanelId(fittedGrid.getPanelId());
            inventory.setDeviceId(fittedGrid.getDeviceId());
            inventory.setDeviceIndex(fittedGrid.getDeviceIndex());
            inventory.setPanelName(fittedGrid.getPanelName());
            inventory.setRoomId(fittedGrid.getRoomId());
            inventory.setRoomName(fittedGrid.getRoomName());
            inventory.setZoneName(zoneMap.get(fittedGrid.getZone()));
            inventory.setBoxId(fittedGrid.getBoxId());
            inventory.setBoxColor(fittedGrid.getBoxColor());
            inventory.setBoxGridId(fittedGrid.getId());
            inventory.setGridColumn(fittedGrid.getColumnNo());
            inventory.setGridRow(fittedGrid.getRowNo());
            Box b = boxService.get(fittedGrid.getBoxId());
            inventory.setIsSingleBox(b.getColumns().equals(1)&&b.getRows().equals(1)?true:false);
            pos.setInventory(inventory);
            positionList.add(pos);
        }
        return fitSuccess;
    }


    private boolean getFittedPanelGridList(Integer boxWidth, Integer boxHeight, List<Panel> panelList, Map<Long, List<PanelGridUsed>> panelGridUsedMap, List<ReagentCombo> comList, List<ReagentPosition> positionList, Date productDate, Date expireDate, String batchNumber, Map<Integer, String> zoneMap) {
        for (int i = 0; i < panelList.size(); i++) {
            List<PanelGridUsed> gridUsedList = panelGridUsedMap.get(panelList.get(i).getId());
            if (gridUsedList == null) {
                gridUsedList = panelService.getPanelGridUsedList(panelList.get(i).getId());
                panelGridUsedMap.put(panelList.get(i).getId(), gridUsedList);
            }
            List<PanelGridUsed> fitList = new ArrayList<>();
            boolean allFit = false;
            PanelGridUsed start = null;
            for (int y = 0; y < panelList.get(i).getRows() - boxHeight + 1; y++) {
                for (int x = 0; x < panelList.get(i).getColumns() - boxWidth + 1; x++) {
                    allFit = true;
                    for (int by = 0; by < boxHeight; by++) {
                        for (int bx = 0; bx < boxWidth; bx++) {
                            int tx = x;
                            int ty = y;
                            int tbx = bx;
                            int tby = by;
                            if (!gridUsedList.stream().anyMatch(gu -> gu.getColumnNo() == tx + tbx && gu.getRowNo() == ty + tby)) {
                                if (bx == 0 && by == 0) {
                                    start = new PanelGridUsed();
                                    start.setColumnNo(tx);
                                    start.setRowNo(ty);
                                }
                                PanelGridUsed fitGrid = new PanelGridUsed();
                                fitGrid.setPanelId(panelList.get(i).getId());
                                fitGrid.setColumnNo(tx + tbx);
                                fitGrid.setRowNo(ty + tby);
                                fitList.add(fitGrid);
                            } else {
                                start = null;
                                allFit = false;
                                fitList.clear();
                                break;
                            }
                        }
                        if (!allFit) {
                            break;
                        }
                    }
                    if (allFit) {
                        break;
                    }
                }
                if (allFit) {
                    break;
                }
            }
            if (allFit) {
                ReagentPosition position = new ReagentPosition();
                position.setExpireDate(expireDate);
                position.setProductDate(productDate);
                position.setBatchNumber(batchNumber);
                position.setReagent(comList);
                position.setGridUsedList(fitList);
                Panel fitPanel = panelList.get(i);
                ReagentInventoryWithOwner inventory = new ReagentInventoryWithOwner();
                inventory.setPanelId(fitPanel.getId());
                inventory.setDeviceId(fitPanel.getDeviceId());
                inventory.setDeviceIndex(fitPanel.getDeviceIndex());
                inventory.setPanelName(fitPanel.getName());
                inventory.setRoomName(fitPanel.getRoomName());
                inventory.setRoomId(fitPanel.getRoomId());
                inventory.setZoneName(zoneMap.get(fitPanel.getZone()));
                position.setPanel(fitPanel);
                position.setInventory(inventory);
                position.setWidth(boxWidth);
                position.setHeight(boxHeight);
                positionList.add(position);
                position.setX(start.getColumnNo());
                position.setY(start.getRowNo());
                gridUsedList.addAll(fitList);
                return true;
            }
        }
        return false;
    }

    private boolean isFitToBoxGrid(Integer unit, BigDecimal size) {
        Map<String, List<Dict>> unitMap = dictService.getUnit();
        if (unitMap.get("摩尔").stream().anyMatch(o -> o.getCode().equals(unit))) {
            return true;
        }
        if (unitMap.get("活性").stream().anyMatch(o -> o.getCode().equals(unit))) {
            return true;
        }
        List<Dict> volDictList = unitMap.get("体积");
        Optional<Dict> opt = volDictList.stream().filter(o -> o.getCode().equals(unit)).findFirst();
        if (opt.isPresent()) {
            Dict volDict = opt.get();
            if (volDict.getSortNo().equals(3) && new BigDecimal(2 / 1000).compareTo(size) >= 0) {
                return true;
            }
            if (volDict.getSortNo().equals(2) && new BigDecimal(2).compareTo(size) >= 0) {
                return true;
            }
            if (volDict.getSortNo().equals(1) && new BigDecimal(2000).compareTo(size) >= 0) {
                return true;
            }
        }
        List<Dict> qualDictList = unitMap.get("质量");
        Optional<Dict> qualDictOpt = qualDictList.stream().filter(o -> o.getCode().equals(unit)).findFirst();
        if (qualDictOpt.isPresent()) {
            Dict qualDict = qualDictOpt.get();
            if (qualDict.getSortNo().equals(6) && new BigDecimal(5 / 1000).compareTo(size) >= 0) {
                return true;
            }
            if (qualDict.getSortNo().equals(5) && new BigDecimal(5).compareTo(size) >= 0) {
                return true;
            }
            if (qualDict.getSortNo().equals(4) && new BigDecimal(5000).compareTo(size) >= 0) {
                return true;
            }
            if (qualDict.getSortNo().equals(3) && new BigDecimal(5000 * 1000).compareTo(size) >= 0) {
                return true;
            }
            if (qualDict.getSortNo().equals(2) && new BigDecimal(5000 * 1000).compareTo(size.divide(new BigDecimal(1000))) >= 0) {
                return true;
            }
            if (qualDict.getSortNo().equals(1) && new BigDecimal(5000 * 1000).compareTo(size.divide(new BigDecimal(1000 * 1000))) >= 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * @return java.math.BigDecimal
     * @Description: 获取该kit总可用量（包括公共，自己私有，分享给自己的）
     * @Params: [labMemberId, kitId, oneKitSpecList]
     * @author wuzhiyu
     * @date 2018/11/20 9:53
     */
    public BigDecimal getKitAllAmount(Long labMemberId, Long kitId, List<KitSpec> oneKitSpecList) {
        BigDecimal minAmount = BigDecimal.valueOf(Long.MAX_VALUE);
        List<ReagentInventory> allInvList = reagentInventoryService.getInventoryList(kitId, labMemberId, null);
        List<ReagentInventory> shareInvList = inventoryShareService.getShareToMeInventoryList(labMemberId, InventoryShareEnum.ACCEPTED, 0);
        if (CollectionUtils.isEmpty(allInvList) && CollectionUtils.isEmpty(shareInvList)) {
            return null;
        }
        List<Long> shareIdList = shareInvList.stream().map(ReagentInventory::getReagentId).distinct().collect(Collectors.toList());
        List<Long> reagentIdList = allInvList.stream().map(ReagentInventory::getReagentId).distinct().collect(Collectors.toList());
        reagentIdList.addAll(shareIdList);
        Long count = reagentIdList.stream().distinct().count();
        if (count < oneKitSpecList.size()) {
            return BigDecimal.valueOf(0);
        }
        for (KitSpec spec : oneKitSpecList) {
            BigDecimal thisAmount = BigDecimal.valueOf(0);
            if (allInvList.size() > 0) {
                List<ReagentInventory> thisSepcList = allInvList.stream().filter(o -> o.getReagentId().equals(spec.getReagentId())).collect(Collectors.toList());
                if (thisSepcList.size() > 0) {
                    thisAmount = thisSepcList.stream().map(ReagentInventory::getAmount).reduce(BigDecimal::add).get();
                }
            }
            BigDecimal shareAmount = BigDecimal.valueOf(0);
            if (shareInvList.size() > 0) {
                List<ReagentInventory> thisShare = shareInvList.stream().filter(o -> o.getReagentId().equals(spec.getReagentId())).collect(Collectors.toList());
                if (thisShare.size() > 0) {
                    shareAmount = thisShare.stream().map(ReagentInventory::getAmount).reduce(BigDecimal::add).get();
                }

            }
            BigDecimal thisKitAmount = ((thisAmount.add(shareAmount)).multiply(spec.getKitSize())).divide(spec.getSize().multiply(BigDecimal.valueOf(spec.getMultiple())), 3, BigDecimal.ROUND_UP);
            if (minAmount.compareTo(thisKitAmount) == 1) {
                minAmount = thisKitAmount;
            }
        }

        return minAmount;
    }

    /**
     * @return java.math.BigDecimal
     * @Description: 获取该组kit库存的可用量
     * @Params: [kitId, labMemberId, groupId, oneSpecList]
     * @author wuzhiyu
     * @date 2018/11/20 10:58
     */
    public BigDecimal getOneGroupKitAmount(Long kitId, Long groupId, UserInfoVo userInfo, List<KitSpec> oneSpecList, List<ReagentInventory> invList) {
        BigDecimal minAmount = BigDecimal.valueOf(Long.MAX_VALUE);
        //List<ReagentInventory> allInvList = reagentInventoryService.getInventoryList(kitId, labMemberId, groupId);
        List<ReagentInventory> allInvList = null;
        if(labMemberService.isOwner(userInfo.getLabId(),userInfo.getLabMemberId()) || labMemberPowerService.isPower(userInfo.getLabId(),userInfo.getLabMemberId(),LabMemberPowerEnum.Power.REAGENT)){
            allInvList = invList.stream().filter(i -> i.getKitId().equals(kitId)  && i.getGroupId().equals(groupId)).collect(Collectors.toList());
        }else {
            allInvList = invList.stream().filter(i -> i.getKitId().equals(kitId) && (userInfo.getLabMemberId().equals(i.getLabMemberId()) || i.getLabMemberId() == null) && i.getGroupId().equals(groupId)).collect(Collectors.toList());
        }

        if (allInvList.size() < 1) {
            return BigDecimal.valueOf(0);
        }
        List<Long> reagentIdList = allInvList.stream().map(ReagentInventory::getReagentId).distinct().collect(Collectors.toList());
        if (reagentIdList.size() < oneSpecList.size()) {
            return BigDecimal.valueOf(0);
        }
        if (oneSpecList.size() == 1) {
            minAmount = allInvList.stream().map(ReagentInventory::getAmount).reduce(BigDecimal::add).get();
        }
        for (KitSpec spec : oneSpecList) {
            BigDecimal thisAmount = allInvList.stream().filter(o -> o.getReagentId().equals(spec.getReagentId())).map(ReagentInventory::getAmount).reduce(BigDecimal::add).get();
            BigDecimal thisKitAmount = (thisAmount.multiply(spec.getKitSize())).divide(spec.getSize().multiply(BigDecimal.valueOf(spec.getMultiple())), RoundingMode.HALF_UP);
            if (minAmount.compareTo(thisKitAmount) >= 0) {
                minAmount = thisKitAmount;
            }
        }
        return minAmount;
    }

    public BigDecimal getOneGroupKitAmount(Long kitId, Long groupId, Long labMemberId, List<KitSpec> oneSpecList) {
        BigDecimal minAmount = BigDecimal.valueOf(Long.MAX_VALUE);
        List<ReagentInventory> allInvList = reagentInventoryService.getInventoryList(kitId, labMemberId, groupId);
        if (allInvList.size() < 1) {
            return BigDecimal.valueOf(0);
        }
        List<Long> reagentIdList = allInvList.stream().map(ReagentInventory::getReagentId).distinct().collect(Collectors.toList());
        if (reagentIdList.size() < oneSpecList.size()) {
            return BigDecimal.valueOf(0);
        }
        if (oneSpecList.size() == 1) {
            minAmount = allInvList.stream().map(ReagentInventory::getAmount).reduce(BigDecimal::add).get();
        }
        for (KitSpec spec : oneSpecList) {
            BigDecimal thisAmount = allInvList.stream().filter(o -> o.getReagentId().equals(spec.getReagentId())).map(ReagentInventory::getAmount).reduce(BigDecimal::add).get();
            BigDecimal thisKitAmount = (thisAmount.multiply(spec.getKitSize())).divide(spec.getSize().multiply(BigDecimal.valueOf(spec.getMultiple())), RoundingMode.HALF_UP);
            if (minAmount.compareTo(thisKitAmount) >= 0) {
                minAmount = thisKitAmount;
            }
        }
        return minAmount;
    }

    /**
     * @return void
     * @Description: 入库
     * @Params: [positionList, labMemberId]
     * @author wuzhiyu
     * @date 2018/11/20 11:25
     */
    public void inventoryIn(InventoryInVo inInfo, UserInfoVo user) {

        List<ReagentInventoryIn> positionList = inInfo.getPositionList();
        Long labMemberId = null;
        if (BooleanUtils.isTrue(inInfo.getIsPrivate())) {
            labMemberId = user.getLabMemberId();
        }
        List<ReagentInventory> newInvList = new ArrayList<>();
        List<PanelGridUsed> newPanelGridUsedList = new ArrayList<>();
        List<Long> boxGridUsed = new ArrayList<>();
        Map<Long, Reagent> reagentMap = new HashMap<>();
        Map<Long, Kit> kitMap = new HashMap<>();
        Map<Long, List<PanelGridUsed>> panelGridUsedMap = new HashMap<>();
        Map<Long, Panel> panelMap = new HashMap<>();
        positionList.forEach(p -> {
            if (p.getReagentList() == null || p.getReagentList().size() < 1 || p.getReagentList().get(0).getReagentId() == null || (p.getBoxGridId() == null && p.getGridUsedList().size() < 1)) {
                throw new BrillilabException(ResultEnum.REQUEST_PARAM_LACK);
            }
        });
        for (ReagentInventoryIn p : positionList) {
            if (CollectionUtils.isEmpty(p.getGridUsedList()) || p.getGridUsedList().size() < 1) {
                for (ReagentCombo r :p.getReagentList()){
                    Long reagentId = r.getReagentId();
                    Reagent reagent = reagentMap.get(reagentId);
                    if (reagent == null) {
                        reagent = reagentService.selectById(reagentId);
                        if (reagent == null | (!reagent.getLabId().equals(user.getLabId()))) {
                            throw new BrillilabException(ResultEnum.DATA_NOT_EXIST);
                        }
                        reagentMap.put(reagent.getId(), reagent);
                    }
                    if (kitMap.get(reagent.getKitId()) == null) {
                        Kit kit = kitService.selectById(reagent.getKitId());
                        kitMap.put(kit.getId(), kit);
                    }
                }
                BoxGrid boxGrid = boxService.getBoxGrid(p.getBoxGridId());
                Long totalSingleGridCount = Long.valueOf(0);
                if (boxGrid.getSpec().equals(0)) {
                    //无分隔试剂盒限制100
                    Integer boxGridInvCount = reagentInventoryService.getBoxGridInventoryCount(boxGrid.getId());
                    Long newCnt = positionList.stream().filter(o -> boxGrid.getId().equals(o.getBoxGridId())).count();
                    totalSingleGridCount = boxGridInvCount + newCnt;
                    if ((boxGridInvCount + newCnt - 100) > 0) {
                        throw new BrillilabException(ResultEnum.DATA_IN_USING);
                    }
                }
                if (boxGrid == null || boxGrid.getIsFill().equals(1) || (!boxGrid.getLabId().equals(user.getLabId()))) {
                    throw new BrillilabException(ResultEnum.SPACE_OCCUPIED);
                }
                if (boxGrid.getLabMemberId() != null && !boxGrid.getLabMemberId().equals(user.getLabMemberId())) {
                    throw new BrillilabException(ResultEnum.USER_NOT_POWER);
                }
                Long combId = reagentInventoryService.generateInventoryCombId();
                for (ReagentCombo r : p.getReagentList()) {
                    Reagent reagent = reagentMap.get(r.getReagentId());
                    ReagentInventory newInv = new ReagentInventory();
                    newInv.setGridRow(boxGrid.getRowNo());
                    newInv.setGridColumn(boxGrid.getColumnNo());
                    newInv.setBoxGridId(boxGrid.getId());//必须前台传
                    newInv.setBoxColor(boxGrid.getBoxColor());
                    newInv.setBoxId(boxGrid.getBoxId());
                    newInv.setKitId(reagent.getKitId());
                    newInv.setReagentId(r.getReagentId());
                    newInv.setReagentName(r.getName());
                    newInv.setKitSpecId(r.getKitSpecId());
                    newInv.setDeviceIndex(boxGrid.getDeviceIndex());
                    newInv.setDeviceId(boxGrid.getDeviceId());
                    newInv.setPanelId(boxGrid.getPanelId());
                    newInv.setPanelName(boxGrid.getPanelName());
                    newInv.setIsDelete(IsDeleteEnum.NO.getValue());
                    newInv.setAmount(r.getSize());
                    newInv.setClassify(reagent.getClassify());
                    newInv.setCreatorId(user.getLabMemberId());
                    newInv.setGroupId(r.getGroupId());//必须前台传
                    newInv.setInUse(0);
                    newInv.setKitType(kitMap.get(reagent.getKitId()).getKitType());
                    newInv.setLabId(user.getLabId());
                    newInv.setRoomId(boxGrid.getRoomId());
                    newInv.setRoomName(boxGrid.getRoomName());
                    newInv.setLabMemberId(labMemberId);
                    newInv.setUnit(r.getUnit());
                    newInv.setProduceDate(p.getProduceDate());
                    newInv.setExpireDate(p.getExpireDate());
                    newInv.setZone(boxGrid.getZone());
                    newInv.setReagentTypeId(r.getReagentTypeId());
                    newInv.setBatchNumber(p.getBatchNumber());
                    newInv.setPosCombId(combId);
                    newInvList.add(newInv);
                    if (boxGrid.getSpec() != 0 || totalSingleGridCount >= 100) {
                        boxGridUsed.add(boxGrid.getId());
                    }
                }
            } else {
                Panel panel = panelMap.get(p.getGridUsedList().get(0).getPanelId());
                if (panel == null) {
                    panel = panelService.get(p.getGridUsedList().get(0).getPanelId());
                    if (panel == null) {
                        throw new BrillilabException(ResultEnum.DATA_NOT_EXIST);
                    }
                    if (panel.getLabMemberId() != null && !panel.getLabMemberId().equals(user.getLabMemberId())) {
                        throw new BrillilabException(ResultEnum.USER_NOT_POWER);
                    }
                    panelMap.put(panel.getId(), panel);
                }
                List<PanelGridUsed> panelGridUsedList = panelGridUsedMap.get(p.getGridUsedList().get(0).getPanelId());
                if (panelGridUsedList == null) {
                    panelGridUsedList = panelService.getPanelGridUsedList(p.getGridUsedList().get(0).getPanelId());
                    panelGridUsedMap.put(p.getGridUsedList().get(0).getPanelId(), panelGridUsedList);
                }
                List<PanelGridUsed> thisUsedList = p.getGridUsedList();
                for (PanelGridUsed u : thisUsedList) {
                    if (panelGridUsedList.stream().filter(db -> db.getPanelId().equals(u.getPanelId()) && db.getRowNo().equals(u.getRowNo()) && db.getColumnNo().equals(u.getColumnNo())).count() > 0) {
                        throw new BrillilabException(ResultEnum.DATA_IN_USING);
                    }
                }
                p.getReagentList().forEach(r -> {
                    Reagent reagent = reagentMap.get(r.getReagentId());
                    if (reagent == null) {
                        reagent = reagentService.selectById(r.getReagentId());
                        if (reagent == null | (!reagent.getLabId().equals(user.getLabId()))) {
                            throw new BrillilabException(ResultEnum.DATA_NOT_EXIST);
                        }
                        reagentMap.put(reagent.getId(), reagent);
                    }
                    if (kitMap.get(reagent.getKitId()) == null) {
                        Kit kit = kitService.selectById(reagent.getKitId());
                        kitMap.put(kit.getId(), kit);
                    }
                });
                List<ReagentCombo> comList = p.getReagentList();
                KitBox kitBox = new KitBox();
                kitBox.setDeviceId(panel.getDeviceId());
                kitBox.setDeviceIndex(panel.getDeviceIndex());
                kitBox.setIsDelete(IsDeleteEnum.NO.getValue());
                kitBox.setIsSingle(comList.size() > 1 ? 0 : 1);
                kitBox.setLabId(user.getLabId());
                kitBox.setLabMemberId(labMemberId);
                String name = new String();
                for (Kit kit : kitMap.values()) {
                    name.concat("_" + kit.getName());
                }
                kitBox.setName(name);
                kitBox.setPanelId(panel.getId());
                kitBox.setPanelName(panel.getName());
                kitBox.setRoomId(panel.getRoomId());
                kitBox.setRoomName(panel.getRoomName());
                kitBox.setZone(panel.getZone());
                List<PanelGridUsed> gridList = p.getGridUsedList();
                Integer x = Integer.valueOf(100);
                Integer y = Integer.valueOf(100);
                Integer maxX = Integer.valueOf(0);
                Integer maxY = Integer.valueOf(0);
                for (PanelGridUsed gu : gridList) {
                    if (gu.getColumnNo() < x) {
                        x = gu.getColumnNo();
                    }
                    if (gu.getRowNo() < y) {
                        y = gu.getRowNo();
                    }
                    if (gu.getColumnNo() > maxX) {
                        maxX = gu.getColumnNo();
                    }
                    if (gu.getRowNo() > maxY) {
                        maxY = gu.getRowNo();
                    }
                }
                kitBox.setWidth(maxX - x + 1);
                kitBox.setHeight(maxY - y + 1);
                kitBox.setX(x);
                kitBox.setY(y);
                kitBoxService.add(kitBox);
                p.getGridUsedList().forEach(gu -> {
                    gu.setKitBoxId(kitBox.getId());
                });
                newPanelGridUsedList.addAll(p.getGridUsedList());
                panelGridUsedList.addAll(p.getGridUsedList());
                Integer zone = panel.getZone();
                Long combId = reagentInventoryService.generateInventoryCombId();
                for (ReagentCombo r : p.getReagentList()) {
                    Reagent thisReagent = reagentMap.get(r.getReagentId());
                    ReagentInventory newInv = new ReagentInventory();
                    newInv.setKitBoxId(kitBox.getId());
                    newInv.setKitId(thisReagent.getKitId());
                    newInv.setReagentId(thisReagent.getId());
                    newInv.setReagentName(thisReagent.getName());
                    newInv.setKitSpecId(r.getKitSpecId());
                    newInv.setDeviceIndex(kitBox.getDeviceIndex());
                    newInv.setDeviceId(kitBox.getDeviceId());
                    newInv.setPanelId(kitBox.getPanelId());
                    newInv.setPanelName(kitBox.getPanelName());
                    newInv.setIsDelete(IsDeleteEnum.NO.getValue());
                    newInv.setAmount(r.getSize());
                    newInv.setClassify(thisReagent.getClassify());
                    newInv.setCreatorId(user.getLabMemberId());
                    newInv.setGroupId(r.getGroupId());//必须前台传
                    newInv.setInUse(0);
                    newInv.setKitType(kitMap.get(thisReagent.getKitId()).getKitType());
                    newInv.setLabId(user.getLabId());
                    newInv.setRoomId(kitBox.getRoomId());
                    newInv.setRoomName(kitBox.getRoomName());
                    newInv.setLabMemberId(labMemberId);
                    newInv.setUnit(r.getUnit());
                    newInv.setProduceDate(p.getProduceDate());
                    newInv.setExpireDate(p.getExpireDate());
                    newInv.setZone(zone);
                    newInv.setReagentTypeId(r.getReagentTypeId());
                    newInv.setKitBoxName(kitBox.getName());
                    newInv.setBatchNumber(p.getBatchNumber());
                    newInv.setPosCombId(combId);
                    newInvList.add(newInv);
                }
            }
        }
        if (newInvList.size() > 0) {
            reagentInventoryService.saveInventoryList(newInvList);
        }
        if (boxGridUsed.size() > 0) {
            boxService.updateBoxGridFill(boxGridUsed, 1);
        }
        if (newPanelGridUsedList.size() > 0) {
            panelService.addPanelGridUsedList(newPanelGridUsedList);
        }
        inventoryRecordService.add(user, kitMap.keySet().stream().collect(Collectors.toList()), InventoryRecordEnum.WAREHOUSING);
    }

    /**
     * @return com.brillilab.domain.vo.inventory.RelateInventoryInfo
     * @Description: TODO
     * @Params: [inventory]
     * @author wuzhiyu
     * @date 2018/11/20 16:21
     */
    public RelateInventoryInfo getRelateInventoryInfo(ReagentInventory inventory) {
        Map<Integer, String> unitMap = dictService.getUnitMap();
        Kit kit = kitService.selectById(inventory.getKitId());
        List<Reagent> reagentList = reagentService.selectList(kit.getId());
        List<KitSpec> specList = kitSpecService.getKitSpecListBySpecId(inventory.getKitSpecId());
        List<ReagentInventory> inventoryList = reagentInventoryService.getInventoryList(kit.getId(), null, inventory.getGroupId());
        RelateInventoryInfo info = new RelateInventoryInfo();
        KitWithUnitNameAndSpec kns = new KitWithUnitNameAndSpec();
        MyBeanUtils.copyProperties(kit, kns);
        kns.setUnitName(unitMap.get(kit.getUnit()));
        info.setKit(kns);
        List<ReagentWithInventoryAndSpec> invList = new ArrayList<>();
        info.setReagentWithInventoryAndSpecList(invList);
        List<LabMemberVo> memList = labMemberService.selectList(kit.getLabId(), null);
        reagentList.forEach(r -> {
            ReagentWithInventoryAndSpec one = new ReagentWithInventoryAndSpec();
            one.setReagent(r);
            KitSpec spec = specList.stream().filter(o -> o.getReagentId().equals(r.getId())).findFirst().get();
            KitSpecWithUnitName spName = new KitSpecWithUnitName();
            MyBeanUtils.copyProperties(spec, spName);
            spName.setUnitName(unitMap.get(spec.getUnit()));
            one.setKitSpec(spName);
            List<ReagentInventory> list = inventoryList.stream().filter(o -> o.getReagentId().equals(r.getId())).collect(Collectors.toList());
            List<ReagentInventoryWithOwner> oList = new ArrayList<>();
            list.forEach(l -> {
                ReagentInventoryWithOwner own = new ReagentInventoryWithOwner();
                MyBeanUtils.copyProperties(l, own);
                own.setUnitName(unitMap.get(l.getUnit()));
                if (l.getLabMemberId() == null) {
                    own.setLabMemberName("公用");
                } else {
                    own.setLabMemberName(memList.stream().filter(m -> m.getLabMemberId().equals(l.getLabMemberId())).findFirst().get().getUserName());
                }
                one.setOwnerName(own.getLabMemberName());
                one.setUnitName(own.getUnitName());
                if (one.getAmount() == null) {
                    one.setAmount(BigDecimal.valueOf(0));
                }
                one.setAmount(one.getAmount().add(l.getAmount()));
                oList.add(own);
            });
            one.setInventoryList(oList);
            invList.add(one);
        });
        return info;
    }

    /**
     * @return void
     * @Description: TODO
     * @Params: []
     * @author wuzhiyu
     * @date 2018/11/20 18:43
     */
    public BoxVo BoxMove(BoxMove boxMove, UserInfoVo user) {
        Map<Integer, String> zoneMap = dictService.getZoneMap();
        List<PanelGridUsed> gridUsedList = boxMove.getPanelGridUsedList();
        panelService.deletePanelGridUsedByBoxId(boxMove.getBoxId(), BoxTypeEnum.REAGENT_BOX);
        List<PanelGridUsed> targetGridUsed = panelService.getPanelGridUsedList(gridUsedList.get(0).getPanelId());
        gridUsedList.forEach(g -> {
            if (targetGridUsed.stream().filter(t -> t.getRowNo().equals(g.getRowNo()) && t.getColumnNo().equals(g.getColumnNo())).count() > 0) {
                throw new BrillilabException(ResultEnum.DATA_IN_USING);
            }
        });
        Box dbBox = boxService.get(boxMove.getBoxId());
        List<BoxVo> targeList = boxService.list(gridUsedList.get(0).getPanelId());
        if (!dbBox.getPanelId().equals(boxMove.getPanelGridUsedList().get(0).getPanelId())) {
            if (!CollectionUtils.isEmpty(targeList)) {
                Optional<BoxVo> opt = targeList.stream().filter(b -> b.getBoxColor().equals(dbBox.getBoxColor())).findFirst();
                if (opt.isPresent()) {
                    throw new BrillilabException("当前平面已有相同编号试剂盒，请选择其他平面");
                }
            }
        }
        Box updateBox = new Box();
        Panel newPanel = panelService.get(gridUsedList.get(0).getPanelId());
        updateBox.setId(boxMove.getBoxId());
        updateBox.setRoomId(newPanel.getRoomId());
        updateBox.setRoomName(newPanel.getRoomName());
        updateBox.setDeviceIndex(newPanel.getDeviceIndex());
        updateBox.setDeviceId(newPanel.getDeviceId());
        updateBox.setPanelId(newPanel.getId());
        updateBox.setPanelName(newPanel.getName());
        updateBox.setX(Integer.valueOf(100));
        updateBox.setY(Integer.valueOf(100));
        updateBox.setZone(newPanel.getZone());
        for (PanelGridUsed used : boxMove.getPanelGridUsedList()) {
            updateBox.setX(Math.min(updateBox.getX(), used.getColumnNo()));
            updateBox.setY(Math.min(updateBox.getY(), used.getRowNo()));
            used.setBoxId(boxMove.getBoxId());
        }
        BoxGrid bg = new BoxGrid();
        bg.setRoomId(newPanel.getRoomId());
        bg.setRoomName(newPanel.getRoomName());
        bg.setDeviceId(newPanel.getDeviceId());
        bg.setDeviceIndex(newPanel.getDeviceIndex());
        bg.setPanelId(newPanel.getId());
        bg.setPanelName(newPanel.getName());
        bg.setZone(newPanel.getZone());
        ReagentInventory upInv = new ReagentInventory();
        upInv.setRoomName(newPanel.getRoomName());
        upInv.setRoomId(newPanel.getRoomId());
        upInv.setDeviceId(newPanel.getDeviceId());
        upInv.setDeviceIndex(newPanel.getDeviceIndex());
        upInv.setPanelId(newPanel.getId());
        upInv.setPanelName(newPanel.getName());
        upInv.setBoxId(boxMove.getBoxId());
        upInv.setZone(newPanel.getZone());
        reagentInventoryService.changMoveBoxInventory(upInv);
        panelService.addPanelGridUsedList(gridUsedList);
        boxService.updateById(updateBox);
        boxService.updateBoxGridPosition(boxMove.getBoxId(), bg);
        BoxVo bv = new BoxVo();
        BeanUtils.copyProperties(dbBox, bv);
        bv.setZoneName(zoneMap.get(dbBox.getZone()));
        bv.setPanelGridUsedList(gridUsedList);
        boolean hasPower = checkUserPower(user, LabMemberPowerEnum.reagent, dbBox.getLabMemberId()) || dbBox.getLabMemberId().equals(user.getLabMemberId());
        bv.setCanSee(hasPower);
        return bv;
    }

    /**
     * @return void
     * @Description: TODO
     * @Params: [kitboxMove]
     * @author wuzhiyu
     * @date 2018/11/20 19:13
     */
    public KitBoxVo kitBoxMoveToPanel(KitBoxMove kitBoxMove, UserInfoVo user) {
        List<PanelGridUsed> gridUsedList = kitBoxMove.getPanelGridUsedList();
        panelService.deletePanelGridUsedByBoxId(kitBoxMove.getKitBoxId(), BoxTypeEnum.KIT_BOX);
        List<PanelGridUsed> targetGridUsed = panelService.getPanelGridUsedList(gridUsedList.get(0).getPanelId());
        gridUsedList.forEach(g -> {
            if (targetGridUsed.stream().filter(t -> t.getRowNo().equals(g.getRowNo()) && t.getColumnNo().equals(g.getColumnNo())).count() > 0) {
                throw new BrillilabException(ResultEnum.DATA_IN_USING);
            }
        });
        KitBox oriKitBox = kitBoxService.get(kitBoxMove.getKitBoxId());
        KitBox updateBox = new KitBox();
        Panel newPanel = panelService.get(gridUsedList.get(0).getPanelId());
        updateBox.setId(kitBoxMove.getKitBoxId());
        updateBox.setRoomId(newPanel.getRoomId());
        updateBox.setRoomName(newPanel.getRoomName());
        updateBox.setDeviceIndex(newPanel.getDeviceIndex());
        updateBox.setDeviceId(newPanel.getDeviceId());
        updateBox.setPanelId(newPanel.getId());
        updateBox.setPanelName(newPanel.getName());
        updateBox.setX(Integer.valueOf(100));
        updateBox.setY(Integer.valueOf(100));
        for (PanelGridUsed used : kitBoxMove.getPanelGridUsedList()) {
            updateBox.setX(Math.min(updateBox.getX(), used.getColumnNo()));
            updateBox.setY(Math.min(updateBox.getY(), used.getRowNo()));
            used.setKitBoxId(kitBoxMove.getKitBoxId());
        }
        List<ReagentInventory> kitBoxInventory = reagentInventoryService.listByKitBoxId(kitBoxMove.getKitBoxId());
        List<ReagentInventory> updateList = new ArrayList<>();
        kitBoxInventory.forEach(k -> {
            ReagentInventory upInv = new ReagentInventory();
            upInv.setId(k.getId());
            upInv.setRoomName(newPanel.getRoomName());
            upInv.setRoomId(newPanel.getRoomId());
            upInv.setDeviceId(newPanel.getDeviceId());
            upInv.setDeviceIndex(newPanel.getDeviceIndex());
            upInv.setPanelId(newPanel.getId());
            upInv.setPanelName(newPanel.getName());
            upInv.setKitBoxId(oriKitBox.getId());
            upInv.setKitBoxName(oriKitBox.getName());
            updateList.add(upInv);
        });
        if (gridUsedList.size() > 0) {
            panelService.addPanelGridUsedList(gridUsedList);
        }
        kitBoxService.update(updateBox);
        if (updateList.size() > 0) {
            reagentInventoryService.updateListInventoryPosition(updateList);
        }

        KitBoxVo bv = new KitBoxVo();
        KitBox dbBox = kitBoxService.get(kitBoxMove.getKitBoxId());
        BeanUtils.copyProperties(dbBox, bv);
        bv.setPanelGridUsedList(gridUsedList);
        boolean hasPower = checkUserPower(user, LabMemberPowerEnum.reagent, dbBox.getLabMemberId()) || dbBox.getLabMemberId().equals(user.getLabMemberId());
        bv.setCanSee(hasPower);
        return bv;
    }

    /**
     * @return void
     * @Description: TODO
     * @Params: [toPanel, targetPanel, inventory]
     * @author wuzhiyu
     * @date 2018/11/21 9:45
     */
    public KitBoxVo boxGridMoveToPanel(BoxGridMoveToPanel toPanel, Panel targetPanel, ReagentInventory inventory, UserInfoVo user) {
        List<PanelGridUsed> targetGridUsed = panelService.getPanelGridUsedList(targetPanel.getId());
        toPanel.getPanelGridUsedList().forEach(g -> {
            if (targetGridUsed.stream().filter(t -> t.getRowNo().equals(g.getRowNo()) && t.getColumnNo().equals(g.getColumnNo())).count() > 0) {
                throw new BrillilabException(ResultEnum.DATA_IN_USING);
            }
        });
        KitBox kitBox = new KitBox();
        kitBox.setRoomId(targetPanel.getRoomId());
        kitBox.setRoomName(targetPanel.getRoomName());
        kitBox.setDeviceId(targetPanel.getDeviceId());
        kitBox.setDeviceIndex(targetPanel.getDeviceIndex());
        kitBox.setPanelId(targetPanel.getId());
        kitBox.setPanelName(targetPanel.getName());
        kitBox.setZone(targetPanel.getZone());
        kitBox.setName(inventory.getReagentName());
        kitBox.setLabMemberId(inventory.getLabMemberId());
        kitBox.setLabId(targetPanel.getLabId());
        kitBox.setIsSingle(1);
        kitBox.setHeight(1);
        kitBox.setWidth(1);
        kitBox.setIsDelete(IsDeleteEnum.NO.getValue());
        kitBox.setX(Integer.valueOf(100));
        kitBox.setY(Integer.valueOf(100));
        for (PanelGridUsed used : toPanel.getPanelGridUsedList()) {
            kitBox.setX(Math.min(kitBox.getX(), used.getColumnNo()));
            kitBox.setY(Math.min(kitBox.getY(), used.getRowNo()));
        }
        kitBoxService.add(kitBox);
        for (PanelGridUsed used : toPanel.getPanelGridUsedList()) {
            used.setKitBoxId(kitBox.getId());
        }
        ReagentInventory newInv = new ReagentInventory();
        newInv.setId(toPanel.getInventoryId());
        newInv.setRoomId(kitBox.getRoomId());
        newInv.setRoomName(kitBox.getRoomName());
        newInv.setDeviceId(kitBox.getDeviceId());
        newInv.setDeviceIndex(kitBox.getDeviceIndex());
        newInv.setPanelName(kitBox.getPanelName());
        newInv.setPanelId(kitBox.getPanelId());
        newInv.setKitBoxId(kitBox.getId());
        newInv.setKitBoxName(inventory.getReagentName());
        newInv.setBoxId(null);
        newInv.setBoxColor(null);
        newInv.setBoxGridId(null);
        newInv.setGridColumn(null);
        newInv.setGridRow(null);
        reagentInventoryService.changBoxInventory(newInv);
        List<Long> boxGridIdList = new ArrayList<>();
        boxGridIdList.add(inventory.getBoxGridId());
        boxService.updateBoxGridFill(boxGridIdList, 0);
        panelService.addPanelGridUsedList(toPanel.getPanelGridUsedList());
        KitBoxVo bv = new KitBoxVo();
        KitBox dbBox = kitBoxService.get(kitBox.getId());
        BeanUtils.copyProperties(dbBox, bv);
        bv.setPanelGridUsedList(toPanel.getPanelGridUsedList());
        boolean hasPower = checkUserPower(user, LabMemberPowerEnum.reagent, dbBox.getLabMemberId()) || dbBox.getLabMemberId().equals(user.getLabMemberId());
        bv.setCanSee(hasPower);
        return bv;
    }

    /**
     * @return void
     * @Description: TODO
     * @Params: [inventory, boxGrid]
     * @author wuzhiyu
     * @date 2018/11/21 10:06
     */
    public BoxGridWithInvVo singleKitBoxMoveToBox(KitBox oldkitBox, BoxGrid boxGrid, UserInfoVo user) {
        if (boxGrid.getIsFill().equals(1)) {
            throw new BrillilabException(ResultEnum.DATA_IN_USING);
        }
        List<ReagentInventory> invList = reagentInventoryService.getInventoryListByKitBoxId(oldkitBox.getId());
        if (CollectionUtils.isEmpty(invList) || invList.size() > 1) {
            throw new BrillilabException(ResultEnum.DATA_NOT_EXIST);
        }
        ReagentInventory inventory = invList.get(0);
        KitBox kitBox = new KitBox();
        kitBox.setId(inventory.getKitBoxId());
        kitBox.setIsDelete(IsDeleteEnum.YES.getValue());
        kitBoxService.update(kitBox);
        panelService.deletePanelGridUsedByBoxId(inventory.getKitBoxId(), BoxTypeEnum.KIT_BOX);
        List<Long> gridIdList = new ArrayList<>();
        gridIdList.add(boxGrid.getId());
        boxService.updateBoxGridFill(gridIdList, 1);
        ReagentInventory newInv = comboNewInventory(inventory.getId(), boxGrid);
        reagentInventoryService.changBoxInventory(newInv);
        BoxGridWithInvVo bv = comboBoxGridWithInvVo(inventory, boxGrid);
        boolean hasPower = checkUserPower(user, LabMemberPowerEnum.reagent, inventory.getLabMemberId()) || inventory.getLabMemberId().equals(user.getLabMemberId());
        bv.setCanSee(hasPower);
        return bv;
    }

    public BoxGridWithInvVo gridMoveToGrid(ReagentInventory inventory, BoxGrid boxGrid, UserInfoVo user) {
        if (boxGrid.getIsFill().equals(1)) {
            throw new BrillilabException(ResultEnum.DATA_IN_USING);
        }
        List<Long> oldGridList = new ArrayList<>();
        oldGridList.add(inventory.getBoxGridId());
        boxService.updateBoxGridFill(oldGridList, 0);
        List<Long> newIdList = new ArrayList<>();
        newIdList.add(boxGrid.getId());
        boxService.updateBoxGridFill(newIdList, 1);
        ReagentInventory newInv = comboNewInventory(inventory.getId(), boxGrid);
        reagentInventoryService.changBoxInventory(newInv);
        BoxGridWithInvVo bv = comboBoxGridWithInvVo(inventory, boxGrid);
        boolean hasPower = checkUserPower(user, LabMemberPowerEnum.reagent, inventory.getLabMemberId()) || inventory.getLabMemberId().equals(user.getLabMemberId());
        bv.setCanSee(hasPower);
        return bv;
    }

    /**
     * @return com.brillilab.domain.vo.inventory.BoxWithGridInvVo
     * @Description: TODO
     * @Params: [boxId, user]
     * @author wuzhiyu
     * @date 2019/1/8 14:59
     */
    public BoxWithGridInvVo getBoxWithGridInventory(Long boxId, UserInfoVo user) {
        Box box = boxService.get(boxId);
        Assert.isTrue(box.getLabId().equals(user.getLabId()), "试剂盒不存在");
        List<Dict> sizeList = dictService.getTubeSize();
        Map<Integer, String> zoneMap = dictService.getZoneMap();
        List<LabMemberVo> memList = labMemberService.selectList(box.getLabId(), null);
        List<ReagentInventory> invList = reagentInventoryService.getBoxInventoryList(boxId);
        List<Long> ids = invList.stream().map(ReagentInventory::getReagentId).distinct().collect(Collectors.toList());
        List<Reagent> reagentList = reagentService.selectByReagentIds(ids);
        List<BoxGrid> gridList = boxService.getGridList(boxId);
        BoxWithGridInvVo bvo = new BoxWithGridInvVo();
        List<BoxGridWithInvVo> list = new ArrayList<>();
        bvo.setGridList(list);
        bvo.setLabMemberId(box.getLabMemberId());
        bvo.setBoxColor(box.getBoxColor());
        bvo.setBoxId(box.getId());
        bvo.setColumns(box.getColumns());
        bvo.setRows(box.getRows());
        bvo.setRoomId(box.getRoomId());
        bvo.setRoomName(box.getRoomName());
        bvo.setDeviceId(box.getDeviceId());
        bvo.setDeviceIndex(box.getDeviceIndex());
        bvo.setPanelId(box.getPanelId());
        bvo.setPanelName(box.getPanelName());
        bvo.setZoneName(zoneMap.get(box.getZone()));
        bvo.setZone(box.getZone());
        bvo.setOwnerName(box.getLabMemberId() == null ? "公用" : memList.stream().filter(m -> m.getLabMemberId().equals(box.getLabMemberId())).findFirst().get().getUserName());
        bvo.setUserReagentType(box.getUserReagentType());
        bvo.setRemark(box.getRemark());
        if (!StringUtils.isEmpty(box.getUserReagentType())) {
            List<String> arr = Splitter.on(",").omitEmptyStrings().splitToList(box.getUserReagentType());
            if (arr != null && arr.size() > 0) {
                List<ReagentTypeVo> typeVoList = reagentTypeService.getTypeList(box.getLabId(), null);
                StringBuffer sb = new StringBuffer();
                for (int x = 0; x < arr.size(); x++) {
                    Long i = new Long(arr.get(x));
                    Optional<ReagentTypeVo> opt = typeVoList.stream().filter(o -> o.getReagentTypeId().equals(i)).findFirst();
                    if (opt.isPresent()) {
                        if (x == arr.size() - 1) {
                            sb.append(opt.get().getName());
                        } else {
                            sb.append(opt.get().getName() + ",");
                        }
                    }
                }
                bvo.setTags(sb.toString());
            }
        }
        bvo.setTubeSize(sizeList.stream().filter(s -> s.getCode().equals(box.getSpec())).findFirst().get().getName());
        gridList.forEach(g -> {
            BoxGridWithInvVo gvo = new BoxGridWithInvVo();
            gvo.setBoxGridId(g.getId());
            gvo.setColumnNo(g.getColumnNo());
            gvo.setRowNo(g.getRowNo());
            Optional<ReagentInventory> invOpt = invList.stream().filter(i -> i.getBoxGridId() != null && i.getBoxGridId().equals(g.getId())).findFirst();
            if (invOpt.isPresent()) {
                gvo.setInventoryId(invOpt.get().getId());
                gvo.setKitId(invOpt.get().getKitId());
                gvo.setLabMemberId(invOpt.get().getLabMemberId());
                gvo.setReagentId(invOpt.get().getReagentId());
                Optional<Reagent> reagentOpt = reagentList.stream().filter(o -> o.getId().equals(invOpt.get().getReagentId())).findFirst();
                if (reagentOpt.isPresent()) {
                    gvo.setZone(reagentOpt.get().getZone());
                    gvo.setZoneName(zoneMap.get(reagentOpt.get().getZone()));
                } else {
                    gvo.setZone(invOpt.get().getZone());
                    gvo.setZoneName(zoneMap.get(invOpt.get().getZone()));
                }
                if (invOpt.get().getLabMemberId() == null || user.hasPower(LabMemberPowerEnum.Power.REAGENT) || user.getLabMemberId().equals(invOpt.get().getLabMemberId())) {
                    gvo.setReagentName(invOpt.get().getReagentName());
                    gvo.setCanSee(true);
                } else {
                    gvo.setCanSee(false);
                }
            }
            list.add(gvo);
        });
        return bvo;
    }

    public SingleGridBoxVo getSingleGridBoxInvetenory(Long boxId, UserInfoVo user) {
        Box box = boxService.get(boxId);
        Assert.isTrue(box.getLabId().equals(user.getLabId()), "试剂盒不存在");
        List<BoxGrid> gridList = boxService.getGridList(boxId);
        Assert.isTrue(gridList.size() == 1, "该盒子不是无分隔试剂盒");
        List<LabMemberVo> memList = labMemberService.selectList(box.getLabId(), null);
        Map<Integer, String> zoneMap = dictService.getZoneMap();
        List<ReagentInventory> invList = reagentInventoryService.getBoxInventoryList(boxId);
        SingleGridBoxVo bvo = new SingleGridBoxVo();
        bvo.setLabMemberId(box.getLabMemberId());
        bvo.setBoxColor(box.getBoxColor());
        bvo.setBoxId(box.getId());
        bvo.setColumns(box.getColumns());
        bvo.setRows(box.getRows());
        bvo.setRoomId(box.getRoomId());
        bvo.setRoomName(box.getRoomName());
        bvo.setDeviceId(box.getDeviceId());
        bvo.setDeviceIndex(box.getDeviceIndex());
        bvo.setPanelId(box.getPanelId());
        bvo.setPanelName(box.getPanelName());
        bvo.setZoneName(zoneMap.get(box.getZone()));
        bvo.setZone(box.getZone());
        bvo.setOwnerName(box.getLabMemberId() == null ? "公用" : memList.stream().filter(m -> m.getLabMemberId().equals(box.getLabMemberId())).findFirst().get().getUserName());
        if (!StringUtils.isEmpty(box.getUserReagentType())) {
            List<String> arr = Splitter.on(",").omitEmptyStrings().splitToList(box.getUserReagentType());
            if (arr != null && arr.size() > 0) {
                List<ReagentTypeVo> typeVoList = reagentTypeService.getTypeList(box.getLabId(), null);
                StringBuffer sb = new StringBuffer();
                for (int x = 0; x < arr.size(); x++) {
                    Long i = new Long(arr.get(x));
                    Optional<ReagentTypeVo> opt = typeVoList.stream().filter(o -> o.getReagentTypeId().equals(i)).findFirst();
                    if (opt.isPresent()) {
                        if (x == arr.size() - 1) {
                            sb.append(opt.get().getName());
                        } else {
                            sb.append(opt.get().getName() + ",");
                        }
                    }
                }
                bvo.setTags(sb.toString());
            }
        }
        bvo.setBoxGridId(gridList.get(0).getId());
        bvo.setColumnNo(gridList.get(0).getColumnNo());
        bvo.setRowNo(gridList.get(0).getRowNo());
        List<SingleGridInv> groupList = new ArrayList<>();
        bvo.setGroupList(groupList);
        if (!CollectionUtils.isEmpty(invList)) {
            List<Long> groupIdList = invList.stream().map(ReagentInventory::getPosCombId).distinct().collect(Collectors.toList());
            groupIdList.forEach(i -> {
                SingleGridInv inv = new SingleGridInv();
                groupList.add(inv);
                List<ReagentInventory> invs = invList.stream().filter(v -> v.getPosCombId().equals(i)).collect(Collectors.toList());
                if (invs.get(0).getLabMemberId() == null || user.hasPower(LabMemberPowerEnum.Power.REAGENT) || user.getLabMemberId().equals(invs.get(0).getLabMemberId())) {
                    inv.setCanSee(true);
                } else {
                    inv.setCanSee(false);
                }
                List<SingleGridInvItem> itemList = new ArrayList<>();
                inv.setInvList(itemList);
                invs.forEach(item -> {
                    SingleGridInvItem newItem = new SingleGridInvItem();
                    newItem.setGroupId(item.getGroupId());
                    newItem.setInventoryId(item.getId());
                    newItem.setKitId(item.getKitId());
                    newItem.setReagentId(item.getReagentId());
                    newItem.setReagentName(item.getReagentName());
                    newItem.setPosCombId(item.getPosCombId());
                    itemList.add(newItem);
                });
            });
        }
        return bvo;
    }

    /**
     * @return com.brillilab.domain.vo.inventory.InventoryInfo
     * @Description: 针对当前库存的同一入库group的kit库存信息
     * @Params: [kitBoxId, user]
     * @author wuzhiyu
     * @date 2019/1/12 14:05
     */
    private InventoryInfo getInventoryInfo(Long kitBoxId, Long boxGridInventoryId, Long singleGridId, Long posCombId, UserInfoVo user) {
        KitBox kitBox = null;
        ReagentInventory gridInv = null;
        List<ReagentInventory> invList = null;
        if (kitBoxId != null) {
            kitBox = kitBoxService.get(kitBoxId);
            Assert.notNull(kitBox, "位置不存在");
        }
        if (boxGridInventoryId != null) {
            gridInv = reagentInventoryService.selectById(boxGridInventoryId);
            Assert.notNull(gridInv, "库存不存在");
        }
        if (kitBoxId != null) {
            invList = reagentInventoryService.getInventoryListByKitBoxId(kitBoxId);
        }
        if (boxGridInventoryId != null) {
            invList = reagentInventoryService.getInventoryList(gridInv.getKitId(), null, gridInv.getGroupId());
        }
        if (posCombId != null && singleGridId != null) {
            BoxGrid bg = boxService.getBoxGrid(singleGridId);
            Assert.isTrue(user.getLabId().equals(bg.getLabId()), "位置不存在");
            invList = reagentInventoryService.listByInventoryGroupId(posCombId);
        }
        if (CollectionUtils.isEmpty(invList)) {
            return new InventoryInfo();
        }
        Assert.isTrue(user.getLabId().equals(invList.get(0).getLabId()), "库存不存在");
        Map<Integer, String> unitMap = dictService.getUnitMap();
        Map<Integer, String> zoneMap = dictService.getZoneMap();
        List<ReagentType> typeList = reagentTypeService.selectLabReagentTypeList(user.getLabId());
        InventoryInfo info = new InventoryInfo();
        info.setCanSee(true);
        if (invList.get(0).getLabMemberId() != null) {
            boolean hasPower = checkUserPower(user, LabMemberPowerEnum.reagent, invList.get(0).getLabMemberId()) || invList.get(0).getLabMemberId().equals(user.getLabMemberId());
            info.setCanSee(hasPower);
        }
        DecimalFormat format = new DecimalFormat("0.00");
        boolean isOneGridBox = posCombId != null;
        if (invList.get(0).getClassify().equals(1)) {
            Long kitId = invList.get(0).getKitId();
            PageVo<InventoryRecord> recordList = inventoryRecordService.selectList(kitId, 1, 5);
            info.setRecordList(recordList.getContent());
            ReagentDetailsVo kit = reagentLogic.getReagentDetails(kitId);
            info.setKitInfo(kit);
            for (ReagentInfoVo rea : kit.getReagentList()) {
                rea.setFirstReagentTypeId(typeList.stream().filter(t->t.getId().equals(rea.getReagentTypeId())).findFirst().get().getParentId());
                List<ReagentInventory> thisInvList = invList.stream().filter(o -> o.getReagentId().equals(rea.getReagentId())).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(thisInvList)) {
                    List<KeyValue<String, Boolean>> posList = new ArrayList<>();
                    KeyValue<String, Boolean> pos = new KeyValue<>();
                    List<InventoryPositionInfo> infoList = new ArrayList<>();
                    pos.setKey("未入库");
                    pos.setValue(null);
                    posList.add(pos);
                    rea.setPositionList(posList);
                    rea.setInvInfoList(infoList);
                } else {
                    BigDecimal total = thisInvList.stream().map(ReagentInventory::getAmount).reduce((x, y) -> x.add(y)).get();
                    rea.setAmountStr(format.format(total) + " " + unitMap.get(rea.getUnit()));
                    List<KeyValue<String, Boolean>> posList = new ArrayList<>();
                    List<InventoryPositionInfo> infoList = new ArrayList<>();
                    if (kitBoxId != null) {
                        setPositionList(posList, thisInvList, zoneMap, kitBoxId, null, rea.getReagentId(), isOneGridBox);
                        composeInvPositionInfo(infoList, thisInvList, zoneMap, kitBoxId, null, rea.getReagentId(), isOneGridBox);
                    } else {
                        setPositionList(posList, thisInvList, zoneMap, null, boxGridInventoryId, rea.getReagentId(), isOneGridBox);
                        composeInvPositionInfo(infoList, thisInvList, zoneMap, null, boxGridInventoryId, rea.getReagentId(), isOneGridBox);
                    }
                    rea.setPositionList(posList);
                    rea.setInvInfoList(infoList);
                }
            }
            return info;
        } else {
            List<InventorySampleInfo> sampleInfoList = new ArrayList<>();
            info.setSampleInfoList(sampleInfoList);
            List<Long> kitIdList = invList.stream().map(ReagentInventory::getKitId).distinct().collect(Collectors.toList());
            List<InventoryRecord> allRecord = new ArrayList<>();
            for (Long kitId : kitIdList) {
                InventorySampleInfo sampleInfo = new InventorySampleInfo();
                SampleInfoVo sample = sampleLogic.getSampleInfo(kitId, null);
                PageVo<InventoryRecord> recordList = inventoryRecordService.selectList(kitId, 1, 5);
                allRecord.addAll(recordList.getContent());
                List<KeyValue<String, Boolean>> posList = new ArrayList<>();
                List<InventoryPositionInfo> infoList = new ArrayList<>();
                if (CollectionUtils.isEmpty(invList)) {
                    KeyValue<String, Boolean> pos = new KeyValue<>();
                    pos.setKey("未入库");
                    pos.setValue(null);
                    posList.add(pos);
                } else {
                    if (kitBoxId != null) {
                        setPositionList(posList, invList, zoneMap, kitBoxId, null, sample.getReagentId(), isOneGridBox);
                        composeInvPositionInfo(infoList, invList, zoneMap, kitBoxId, null, sample.getReagentId(), isOneGridBox);
                    } else {
                        setPositionList(posList, invList, zoneMap, null, boxGridInventoryId, sample.getReagentId(), isOneGridBox);
                        composeInvPositionInfo(infoList, invList, zoneMap, null, boxGridInventoryId, sample.getReagentId(), isOneGridBox);
                    }
                }
                sampleInfo.setInvInfoList(infoList);
                sampleInfo.setPositionList(posList);
                sampleInfo.setSampleInfo(sample);
                sampleInfoList.add(sampleInfo);
            }
            info.setRecordList(allRecord);
            return info;
        }
    }

    /**
     *
     */


    public List<KitInventory> getReagentInventoryList(Kit kit, UserInfoVo user) {
        List<ReagentInventory> invList = new ArrayList<>();
        invList = reagentInventoryService.getInventoryList(kit.getId(), null, null);
        if (invList.size() <= 0) {
            return new ArrayList<>();
        }
        List<Reagent> reagentList = reagentService.selectList(kit.getId());
        List<LabMemberVo> memList = labMemberService.selectList(user.getLabId(), null);
        List<Long> groupIdList = invList.stream().map(ReagentInventory::getGroupId).distinct().collect(Collectors.toList());
        //List<Long> boxIdList = invList.stream().filter(i -> i.getBoxId() != null).map(ReagentInventory::getBoxId).distinct().collect(Collectors.toList());
        //List<Box> boxList = new ArrayList<>();
        //if (!CollectionUtils.isEmpty(boxIdList)) {
        //    boxList = boxService.listByIdList(boxIdList);
        //}
        List<KitInventory> voList = new ArrayList<>();
        List<KitSpec> specList = kitSpecService.getKitSpecListBySpecId(invList.get(0).getKitSpecId());
        Map<Integer, String> unitMap = dictService.getUnitMap();
        //Map<Integer, String> zoneMap = dictService.getZoneMap();
        //Map<Long, Panel> panelCache = new HashMap<>();
        for (Long o : groupIdList) {
            KitInventory kitInventory = new KitInventory();
            List<ReagentInventory> thisGroup = invList.stream().filter(inv -> inv.getGroupId().equals(o)).collect(Collectors.toList());
            kitInventory.setKitId(kit.getId());
            kitInventory.setName(kit.getName());
            kitInventory.setReagentCount(reagentList.size());
            kitInventory.setKitType(kit.getKitType());
            kitInventory.setKitUnitName(unitMap.get(kit.getUnit()));
            kitInventory.setKitUnit(kit.getUnit());
            if (thisGroup.get(0).getLabMemberId() != null) {
                kitInventory.setLabMemberName(memList.stream().filter(m -> m.getLabMemberId().equals(thisGroup.get(0).getLabMemberId())).findFirst().get().getUserName());
                kitInventory.setCanUse(checkUserPower(user, LabMemberPowerEnum.reagent, thisGroup.get(0).getLabMemberId()) || thisGroup.get(0).getLabMemberId().equals(user.getLabMemberId()));
            } else {
                kitInventory.setLabMemberName("公用");
                kitInventory.setCanUse(true);
            }
            kitInventory.setAmount(getOneGroupKitAmount(kit.getId(), o, user, specList, invList));
            kitInventory.setBatchNumber(thisGroup.get(0).getBatchNumber());
            kitInventory.setExpireDate(thisGroup.get(0).getExpireDate());
            kitInventory.setProduceDate(thisGroup.get(0).getProduceDate());
            kitInventory.setGroupId(o);
            kitInventory.setLabMemberId(thisGroup.get(0).getLabMemberId());
            kitInventory.setAllIn(specList.size() == thisGroup.stream().map(ReagentInventory::getReagentId).distinct().count());
            List<ReagentInventoryWithOwner> reagentInvList = new ArrayList<>();
            kitInventory.setReagentInventoryWithOwnerList(reagentInvList);
            //Set<Long> reagentIdCache = new HashSet<>();
            //for (ReagentInventory g : thisGroup) {
            //    Panel thisPanel = panelCache.get(g.getPanelId());
            //    if (thisPanel == null) {
            //        thisPanel = panelService.get(g.getPanelId());
            //        panelCache.put(thisPanel.getId(), thisPanel);
            //    }
            //    ReagentInventoryWithOwner owner = new ReagentInventoryWithOwner();
            //    MyBeanUtils.copyProperties(g, owner);
            //    owner.setUnitName(unitMap.get(owner.getUnit()));
            //    owner.setZoneName(zoneMap.get(thisPanel.getZone()));
            //    owner.setLabMemberName(kitInventory.getLabMemberName());
            //    owner.setPanelRows(thisPanel.getRows());
            //    owner.setPanelColumns(thisPanel.getColumns());
            //    owner.setIsSingleBox(false);
            //    if (owner.getBoxId() != null) {
            //        Optional<Box> boxOpt = boxList.stream().filter(b -> b.getId().equals(owner.getBoxId())).findFirst();
            //        if (boxOpt.isPresent()) {
            //            if (boxOpt.get().getRows() == 1 && boxOpt.get().getColumns() == 1) {
            //                owner.setIsSingleBox(true);
            //            }
            //        }
            //    }
            //    reagentInvList.add(owner);
            //    if (g.getKitBoxId() != null) {
            //        List<PanelGridUsed> panelGridUsedList = panelService.getPanelGridUsedListByBoxId(g.getKitBoxId(), BoxTypeEnum.KIT_BOX);
            //        owner.setGridUsedList(panelGridUsedList);
            //    }
            //    reagentIdCache.add(g.getReagentId());
            //}
            //specList.forEach(sp -> {
            //    if (!reagentIdCache.contains(sp.getReagentId())) {
            //        ReagentInventoryWithOwner owner = new ReagentInventoryWithOwner();
            //        Reagent thisRea = reagentList.stream().filter(r -> r.getId().equals(sp.getReagentId())).findFirst().get();
            //        owner.setZoneName(zoneMap.get(thisRea.getZone()));
            //        owner.setUnitName(unitMap.get(thisRea.getUnit()));
            //        owner.setReagentId(thisRea.getId());
            //        owner.setReagentName(thisRea.getName());
            //        owner.setUnit(thisRea.getUnit());
            //        owner.setZone(thisRea.getZone());
            //        owner.setClassify(thisRea.getClassify());
            //        owner.setGroupId(o);
            //        owner.setKitId(thisRea.getKitId());
            //        owner.setKitSpecId(sp.getId());
            //        owner.setKitType(kit.getKitType());
            //        owner.setReagentTypeId(thisRea.getReagentTypeId());
            //        owner.setLabId(thisRea.getLabId());
            //        reagentInvList.add(owner);
            //    }
            //});
            voList.add(kitInventory);
        }
//        inventoryRecordService.add(user, kit.getId(), InventoryRecordEnum.SEE);
        return voList;
    }

    public List<KitInventory> sampleInventoryList(Long sampleGroupId, UserInfoVo user) {

        List<ReagentInventory> invList = new ArrayList<>();
        invList = reagentInventoryService.getSampleGroupInventoryList(sampleGroupId, null);
        List<KitInventory> voList = new ArrayList<>();
        if (invList.size() <= 0) {
            return voList;
        }
        if (!invList.get(0).getLabId().equals(user.getLabId())) {
            throw new BrillilabException(ResultEnum.USER_NOT_POWER);
        }
        List<LabMemberVo> memList = labMemberService.selectList(user.getLabId(), null);
        List<SampleVo> sampleVoList = kitService.sampleByKitGroup(sampleGroupId);
        if (sampleVoList != null && sampleVoList.size() < 1) {
            return voList;
        }
        if (!sampleVoList.get(0).getKit().getLabId().equals(user.getLabId())) {
            throw new BrillilabException(ResultEnum.USER_NOT_POWER);
        }
        List<Long> boxIdList = invList.stream().filter(i -> i.getBoxId() != null).map(ReagentInventory::getBoxId).distinct().collect(Collectors.toList());
        List<Box> boxList = boxService.listByIdList(boxIdList);

        List<Dict> dictList = dictService.getAllUnit();
        Map<Integer, String> zoneMap = dictService.getZoneMap();
        Map<Integer, String> unitMap = dictService.getUnitMap();
        Map<Long, Panel> panelCache = new HashMap<>();
        for (SampleVo s : sampleVoList) {
            List<ReagentInventory> thisSampleInvs = invList.stream().filter(inv -> inv.getKitId().equals(s.getKit().getId())).collect(Collectors.toList());
            if (thisSampleInvs.size() > 0) {
                KitInventory kitInventory = new KitInventory();
                kitInventory.setKitId(s.getKit().getId());
                kitInventory.setName(s.getKit().getName());
                kitInventory.setReagentCount(1);
                kitInventory.setKitType(s.getKit().getKitType());
                kitInventory.setKitUnitName(unitMap.get(s.getKit().getUnit()));
                List<KitSpec> specList = new ArrayList<>();
                specList.add(s.getKitSpec());
                List<ReagentInventoryWithOwner> reagentInvList = new ArrayList<>();
                kitInventory.setReagentInventoryWithOwnerList(reagentInvList);
                kitInventory.setAmount(getOneGroupKitAmount(s.getKit().getId(), thisSampleInvs.get(0).getGroupId(), user, specList, invList));
                kitInventory.setBatchNumber(invList.get(0).getBatchNumber());
                kitInventory.setExpireDate(invList.get(0).getExpireDate());
                kitInventory.setProduceDate(invList.get(0).getProduceDate());
                kitInventory.setLabMemberId(thisSampleInvs.get(0).getLabMemberId());
                //if (thisSampleInvs.get(0).getLabMemberId() != null) {
                //    //kitInventory.setCanUse(checkUserPower(user, LabMemberPowerEnum.reagent, thisSampleInvs.get(0).getLabMemberId()) || thisSampleInvs.get(0).getLabMemberId().equals(user.getLabMemberId()));
                //    //kitInventory.setLabMemberName(memList.stream().filter(m -> m.getLabMemberId().equals(thisSampleInvs.get(0).getLabMemberId())).findFirst().get().getUserName());
                //} else {
                //    //kitInventory.setLabMemberName("公用");
                //    //kitInventory.setCanUse(true);
                //}
                thisSampleInvs.forEach(g -> {
                    Panel thisPanel = panelCache.get(g.getPanelId());
                    if (thisPanel == null) {
                        thisPanel = panelService.get(g.getPanelId());
                        panelCache.put(thisPanel.getId(), thisPanel);
                    }
                    ReagentInventoryWithOwner owner = new ReagentInventoryWithOwner();
                    MyBeanUtils.copyProperties(g, owner);
                    owner.setUnitName(unitMap.get(owner.getUnit()));
                    owner.setIsSingleBox(false);
                    if (owner.getBoxId() != null) {
                        Optional<Box> thisBoxOpt = boxList.stream().filter(b -> b.getId().equals(owner.getBoxId())).findFirst();
                        if (thisBoxOpt.isPresent()) {
                            if (thisBoxOpt.get().getColumns().equals(1) && thisBoxOpt.get().getRows().equals(1)) {
                                owner.setIsSingleBox(true);
                            }
                        }
                    }
                    owner.setUnitName(dictList.stream().filter(d -> d.getCode().equals(owner.getUnit())).findFirst().get().getName());
                    if (g.getLabMemberId() != null) {
                        owner.setCanUse(checkUserPower(user, LabMemberPowerEnum.reagent, g.getLabMemberId()) || g.getLabMemberId().equals(user.getLabMemberId()));
                        owner.setLabMemberName(memList.stream().filter(m -> m.getLabMemberId().equals(g.getLabMemberId())).findFirst().get().getUserName());
                    } else {
                        owner.setLabMemberName("公用");
                        owner.setCanUse(true);
                    }
                    owner.setZoneName(zoneMap.get(owner.getZone()));
                    owner.setPanelRows(thisPanel.getRows());
                    owner.setPanelColumns(thisPanel.getColumns());
                    if (g.getKitBoxId() != null) {
                        List<PanelGridUsed> panelGridUsedList = panelService.getPanelGridUsedListByBoxId(g.getKitBoxId(), BoxTypeEnum.KIT_BOX);
                        owner.setGridUsedList(panelGridUsedList);
                    }
                    reagentInvList.add(owner);
                });
                voList.add(kitInventory);
            }
        }
        return voList;
    }

    public PageVo<ReagentInventoryWithOwner> getSpaceInventoryVoPaged(Long labId, SpaceInventoryPaged search) {
        Map<Integer, String> zoneMap = dictService.getZoneMap();
        PageVo<ReagentInventoryWithOwner> list = reagentInventoryService.getSpaceInventoryPaged(labId, search);
        if (!CollectionUtils.isEmpty(list.getContent())) {
            List<Long> panelIdList = list.getContent().stream().map(ReagentInventory::getPanelId).distinct().collect(Collectors.toList());
            List<Panel> panelList = panelService.getListByIdList(panelIdList);
            List<PanelGridUsed> panelGridUsedList = panelService.getPanelGridUsedListByIdList(panelIdList);
            List<Long> singleBoxIdList = boxService.getLabSingleBoxIdList(labId);
            list.getContent().forEach(l -> {
                if (l.getKitBoxId() != null) {
                    Panel panel = panelList.stream().filter(p -> p.getId().equals(l.getPanelId())).findFirst().get();
                    l.setPanelColumns(panel.getColumns());
                    l.setPanelRows(panel.getRows());
                    l.setGridUsedList(panelGridUsedList.stream().filter(g -> g.getKitBoxId() != null && g.getKitBoxId().equals(l.getKitBoxId())).collect(Collectors.toList()));
                    l.setIsSingleBox(l.getBoxId() == null ? false : singleBoxIdList.contains(l.getBoxId()));
                }
                l.setZoneName(zoneMap.get(l.getZone()));
            });
        }
        return list;
    }

    public boolean deleteSingleInventory(Long inventoryId) {
        ReagentInventory inventory = reagentInventoryService.selectById(inventoryId);
        reagentInventoryService.deleteById(inventoryId);
        processInventoryDelete(inventory);
        return true;
    }

    /**
     * 删除试剂/样品包括库存和位置信息
     * @param kitId
     * @return
     */
    public boolean deleteKitInventory(Long kitId) {
        List<ReagentInventory> invList = reagentInventoryService.selectListByKitId(kitId);
        if (!CollectionUtils.isEmpty(invList)) {
            ReagentInventory one=invList.get(0);
            if(one.getClassify().equals(KitEnum.Classify.SAMPLE.getValue())){
                deleteSampleLocationInfo(invList,one.getPosCombId());
            }else if(one.getClassify().equals(KitEnum.Classify.REAGENT.getValue())){
                deleteKitLocationInfo(invList);
            }
        }
        reagentInventoryService.deleteByKitId(kitId);
        return true;
    }

    private void deleteSampleLocationInfo(List<ReagentInventory> invList,Long posCombId) {
        List<ReagentInventory> sampleGroupInventoryList=reagentInventoryService.listByInventoryGroupId(posCombId);
        if(sampleGroupInventoryList.size()==invList.size()){
            deleteKitLocationInfo(invList);
        }
    }

    private void deleteKitLocationInfo(List<ReagentInventory> invList) {
        List<Long> kitBoxIdList = invList.stream().filter(k -> k.getKitBoxId() != null).map(ReagentInventory::getKitBoxId).distinct().collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(kitBoxIdList)) {
            kitBoxService.deleteListById(kitBoxIdList);
            panelService.deletePanelGridUsedByBoxIdList(kitBoxIdList, BoxTypeEnum.KIT_BOX);
        }
        List<Long> boxGridIdList = invList.stream().filter(g -> g.getBoxGridId() != null).map(ReagentInventory::getBoxGridId).distinct().collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(boxGridIdList)) {
            boxService.updateBoxGridFill(boxGridIdList, 0);
        }
    }

    public boolean deleteInventoryByIdList(List<Long> inventoryIdList) {
        List<ReagentInventory> invList = reagentInventoryService.selectList(inventoryIdList, IsDeleteEnum.NO.getValue());
        reagentInventoryService.deleteBatch(inventoryIdList);
        invList.forEach(inv -> {
            processInventoryDelete(inv);
        });
        return true;
    }

    private void composeInvPositionInfo(List<InventoryPositionInfo> infoList, List<ReagentInventory> invList, Map<Integer, String> zoneMap, Long kitBoxId, Long boxGridInventoryId, Long reagentId, boolean isOneGrid) {
        invList.forEach(p -> {
            InventoryPositionInfo pos = new InventoryPositionInfo();
            pos.setIsOneGrid(isOneGrid);
            pos.setPosCombId(p.getPosCombId());
            pos.setRoomName(p.getRoomName());
            pos.setDeviceIndex(p.getDeviceIndex());
            pos.setPanelName(p.getPanelName());
            Panel panel = panelService.get(p.getPanelId());
            pos.setColumns(panel.getColumns());
            pos.setRows(panel.getRows());
            pos.setZoneName(zoneMap.get(p.getZone()));
            if (p.getBoxId() != null) {
                pos.setBoxColor(p.getBoxColor());
                pos.setGridColumn(p.getGridColumn());
                pos.setGridRow(p.getGridRow());
                List<PanelGridUsed> gridUseds = panelService.getPanelGridUsedListByBoxId(p.getBoxId(), BoxTypeEnum.REAGENT_BOX);
                pos.setGridUsedList(gridUseds);
            } else {
                List<PanelGridUsed> gridUseds = panelService.getPanelGridUsedListByBoxId(p.getKitBoxId(), BoxTypeEnum.KIT_BOX);
                pos.setGridUsedList(gridUseds);
            }
            if (kitBoxId != null) {
                pos.setCurrent(p.getKitBoxId().equals(kitBoxId) && p.getReagentId().equals(reagentId) ? true : false);
            } else {
                pos.setCurrent(p.getId().equals(boxGridInventoryId) && p.getReagentId().equals(reagentId) ? true : false);
            }
            infoList.add(pos);
        });
    }

    private void processInventoryDelete(ReagentInventory inv) {
        if (inv.getKitBoxId() != null) {
            List<ReagentInventory> list = reagentInventoryService.getInventoryListByKitBoxId(inv.getKitBoxId());
            if (CollectionUtils.isEmpty(list)) {
                kitBoxService.delete(inv.getKitBoxId(), SpaceTypeEnum.BOX);
                panelService.deletePanelGridUsedByBoxId(inv.getKitBoxId(), BoxTypeEnum.KIT_BOX);
            }
        }
        if (inv.getBoxGridId() != null) {
            List<Long> idList = new ArrayList<>();
            idList.add(inv.getBoxGridId());
            boxService.updateBoxGridFill(idList, 0);
        }
    }

    private void setPositionList(List<KeyValue<String, Boolean>> posList, List<ReagentInventory> invList, Map<Integer, String> zoneMap, Long kitBoxId, Long boxGridInventoryId, Long reagentId, boolean isOneGridBox) {
        invList.forEach(p -> {
            KeyValue<String, Boolean> pos = new KeyValue<>();
            if (isOneGridBox) {
                pos.setKey(p.getRoomName() + "->" + p.getDeviceIndex() + "[" + zoneMap.get(p.getZone()) + "]" + "->" + p.getPanelName() + (p.getKitBoxId() != null ? "" : ("->" + p.getBoxColor())));
            } else {
                pos.setKey(p.getRoomName() + "->" + p.getDeviceIndex() + "[" + zoneMap.get(p.getZone()) + "]" + "->" + p.getPanelName() + (p.getKitBoxId() != null ? "" : ("->" + p.getBoxColor() + "->" + p.getGridRow() + p.getGridColumn())));
            }
            if (kitBoxId != null) {
                pos.setValue(p.getKitBoxId().equals(kitBoxId) && p.getReagentId().equals(reagentId) ? true : false);
            } else {
                pos.setValue(p.getId().equals(boxGridInventoryId) && p.getReagentId().equals(reagentId) ? true : false);
            }
            posList.add(pos);
        });
    }

    private boolean checkUserPower(UserInfoVo user, String power, Long labMemberId) {
        //return user.getLabMemberId().equals(labMemberId);
        return user.getPowers().stream().anyMatch(p -> p.getPower().equals(power)) || user.getLabMemberId().equals(labMemberId);
    }

    private BoxGridWithInvVo comboBoxGridWithInvVo(ReagentInventory inventory, BoxGrid boxGrid) {
        BoxGridWithInvVo bv = new BoxGridWithInvVo();
        bv.setCanSee(true);
        bv.setReagentId(inventory.getReagentId());
        bv.setKitId(inventory.getKitId());
        bv.setInventoryId(inventory.getId());
        bv.setRowNo(boxGrid.getRowNo());
        bv.setColumnNo(boxGrid.getColumnNo());
        bv.setBoxGridId(boxGrid.getId());
        bv.setReagentName(inventory.getReagentName());
        return bv;
    }

    private ReagentInventory comboNewInventory(Long inventoryId, BoxGrid boxGrid) {
        ReagentInventory newInv = new ReagentInventory();
        newInv.setId(inventoryId);
        newInv.setRoomId(boxGrid.getRoomId());
        newInv.setRoomName(boxGrid.getRoomName());
        newInv.setDeviceId(boxGrid.getDeviceId());
        newInv.setDeviceIndex(boxGrid.getDeviceIndex());
        newInv.setPanelName(boxGrid.getPanelName());
        newInv.setPanelId(boxGrid.getPanelId());
        newInv.setKitBoxId(null);
        newInv.setBoxId(boxGrid.getBoxId());
        newInv.setBoxColor(boxGrid.getBoxColor());
        newInv.setBoxGridId(boxGrid.getId());
        newInv.setGridColumn(boxGrid.getColumnNo());
        newInv.setGridRow(boxGrid.getRowNo());
        return newInv;
    }

    public InventoryInfo getKitBoxInventoryInfo(Long kitBoxId, UserInfoVo user) {
        return getInventoryInfo(kitBoxId, null, null, null, user);
    }

    public InventoryInfo getBoxGridInventoryInfo(Long inventoryId, UserInfoVo user) {
        return getInventoryInfo(null, inventoryId, null, null, user);
    }

    public InventoryInfo getSingleGridBoxGroupInventoryInfo(Long boxGridId, Long posCombId, UserInfoVo user) {
        return getInventoryInfo(null, null, boxGridId, posCombId, user);
    }

    public List<ReagentInventory> getReagentInventoryDeleteList(Long kitId, UserInfoVo user) {
        List<ReagentInventory> inventoryList = new ArrayList<ReagentInventory>();
        if (user.hasPower(LabMemberPowerEnum.Power.REAGENT)) {
            inventoryList = reagentInventoryService.getInventoryList(kitId, null, null);
        } else {
            inventoryList = reagentInventoryService.getInventoryList(kitId, user.getLabMemberId(), null);
        }
        return inventoryList;
    }

    public Integer getDeviceGroupInventoryCount(Long deviceGroupId, UserInfoVo user) {
        List<Device> deviceGroup = deviceService.listDeviceGroupId(deviceGroupId);
        if (!CollectionUtils.isEmpty(deviceGroup)) {
            int count = 0;
            for (Device d : deviceGroup) {
                count += reagentInventoryService.InventoryCountInSpace(d.getId(), SpaceTypeEnum.DEVICE);
            }
            return count;
        }
        return 0;
    }

    /**
     * 删除试剂开锁逻辑
     *
     * @param inventoryIds
     * @param userInfo
     * @return
     */
    public boolean deleteUnlock(List<Long> inventoryIds, UserInfoVo userInfo) {

        List<DeviceUnlock> deviceUnlocks = reagentInventoryService.selectKitUsageDeviceUnLockList(inventoryIds);

        Assert.isTrue(deviceUnlocks != null && deviceUnlocks.size() == 1, "数据异常！");

        DeviceUnlock deviceUnlock = deviceUnlocks.get(0);

        //新增记录
        List<ReagentInventory> inventories = reagentInventoryService.selectList(inventoryIds, BoolEnum.FALSE.getValue());
        List<InventoryDeleteRecord> deleteRecords = inventories.stream().map(inventory -> {
            InventoryDeleteRecord deleteRecord = new InventoryDeleteRecord();
            deleteRecord.setInventoryId(inventory.getId());
            deleteRecord.setDeviceId(deviceUnlock.getDeviceId());
            return deleteRecord;
        }).collect(Collectors.toList());
        inventoryDeleteRecordService.insertBatch(deleteRecords);

        //使用websocket发送设备信息、取用信息给一体机
        Map<String, Object> data = new HashMap<>();
        data.put("labMemberId", userInfo.getLabMemberId());
        data.put("labMemberName", userInfo.getName());
        data.put("deviceId", deviceUnlock.getDeviceId());
        onsProducer.sendBroadcastMessage(onsProducer.getOnsProperties().webSocketAioTopic, new OnsMessageVo(OnsMessageEnum.UNLOCK, data, deviceUnlock.getDeviceNo()));

        //创建关锁时任务 取用后5分钟未关锁
        List<Long> deleteRecordIds = deleteRecords.stream().map(InventoryDeleteRecord::getId).distinct().collect(Collectors.toList());
        createUnlockJob(deleteRecordIds, deviceUnlock.getDeviceId(), userInfo);
        return true;
    }

    private void createUnlockJob(List<Long> deleteRecordIds, Long deviceId, UserInfoVo userInfo) {

        HardWareOperateRecord lock = hardwareOperateRecordService.selectLockByDeviceId(deviceId);

        LockOperation lockOperation = new LockOperation();
        lockOperation.setLockId(lock.getId());
        lockOperation.setDeviceId(deviceId);
        lockOperation.setOperate(LockOperationEnum.UNLOCK.getValue());
        lockOperation.setLabId(userInfo.getLabId());
        lockOperation.setLabMemberId(userInfo.getLabMemberId());
        lockOperationService.insert(lockOperation);

        long FIVE_MINUTE = 5 * 60 * 1000L;
        JobDataMap map = new JobDataMap();
        map.put("recordIds", deleteRecordIds);
        map.put("operateId", lockOperation.getId());
        Date startDate = new Date(System.currentTimeMillis() + FIVE_MINUTE);
        String jobGroup = JobConstants.JOB_GROUP_DELETE_UNLOCK;
        String jobId = jobGroup + lockOperation.getId();
        scheduler.createJob(InventoryDeleteJob.class, jobId, jobGroup, QuartzUtils.getCronExpr(startDate), map);

        lockOperation.setJobGroup(jobGroup);
        lockOperation.setJobName(jobId);
        lockOperationService.update(lockOperation);
    }

    /**
     * 删除试剂关锁逻辑
     *
     * @param deviceId
     * @return
     */
    public boolean deleteLock(Long deviceId) {
        //查找记录
        List<InventoryDeleteRecord> deleteRecords = inventoryDeleteRecordService.selectList(deviceId, BoolEnum.FALSE.getValue());

        //删除库存
        List<Long> inventoryIds = deleteRecords.stream().map(InventoryDeleteRecord::getInventoryId).distinct().collect(Collectors.toList());
        reagentInventoryService.deleteBatch(inventoryIds);

        //更新记录为成功
        deleteRecords.forEach(e -> e.setSuccess(BoolEnum.TRUE.getValue()));

        if (deleteRecords.size() > 0) {
            return inventoryDeleteRecordService.updateBatch(deleteRecords);
        }

        return true;
    }

    /**
     * 删除确认
     *
     * @param inventoryIds
     * @param userInfo
     * @return
     */
    public boolean deleteConfirm(List<Long> inventoryIds, UserInfoVo userInfo) {
        List<ReagentInventory> inventories = reagentInventoryService.selectList(inventoryIds, BoolEnum.FALSE.getValue());
        //权限
        if (!labMemberService.isOwner(userInfo.getLabId(), userInfo.getLabMemberId())
                && !labMemberPowerService.isPower(userInfo.getLabId(), userInfo.getLabMemberId(), LabMemberPowerEnum.Power.REAGENT)) {
            inventories.forEach(e -> {
                Assert.isTrue(e.getLabId().equals(userInfo.getLabId()), "库存非该实验室，无法删除！");
                Assert.isTrue(e.getLabMemberId() == null || (e.getLabMemberId() != null && e.getLabMemberId().equals(userInfo.getLabMemberId())), "库存非公有且不属于该成员，无法删除！");
            });
        }
        return reagentInventoryService.deleteBatch(inventoryIds) > 0;
    }

    public List<ReagentInventoryWithOwner> getReagentInventoryDetailList(Long kitId, Long groupId, UserInfoVo user) {
        Kit kit = kitService.selectById(kitId);
        Assert.isTrue(kit.getLabId().equals(user.getLabId()), ResultEnum.DATA_NOT_EXIST.getMessage());
        Map<Integer, String> unitMap = dictService.getUnitMap();
        Map<Integer, String> zoneMap = dictService.getZoneMap();
        List<ReagentInventory> thisGroup = reagentInventoryService.getInventoryList(kitId, null, groupId);
        List<KitSpec> specList = kitSpecService.getKitSpecListBySpecId(thisGroup.get(0).getKitSpecId());
        List<ReagentInventoryWithOwner> reagentInvList = new ArrayList<>();
        Map<Long, Panel> panelCache = new HashMap<>();
        List<Long> boxIdList = thisGroup.stream().filter(i -> i.getBoxId() != null).map(ReagentInventory::getBoxId).distinct().collect(Collectors.toList());
        List<Reagent> reagentList = reagentService.selectList(kitId);
        List<LabMemberVo> memList = labMemberService.selectList(user.getLabId(), null);
        List<Box> boxList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(boxIdList)) {
            boxList = boxService.listByIdList(boxIdList);
        }
        Set<Long> reagentIdCache = new HashSet<>();
        List<ReagentType> typeList = reagentTypeService.selectLabReagentTypeList(user.getLabId());
        for (ReagentInventory g : thisGroup) {
            Panel thisPanel = panelCache.get(g.getPanelId());
            if (thisPanel == null) {
                thisPanel = panelService.get(g.getPanelId());
                panelCache.put(thisPanel.getId(), thisPanel);
            }
            ReagentInventoryWithOwner owner = new ReagentInventoryWithOwner();
            MyBeanUtils.copyProperties(g, owner);
            owner.setFirstReagentTypeId(typeList.stream().filter(t->t.getId().equals(owner.getReagentTypeId())).findFirst().get().getParentId());
            owner.setUnitName(unitMap.get(owner.getUnit()));
            owner.setZoneName(zoneMap.get(thisPanel.getZone()));
            if (thisGroup.get(0).getLabMemberId() != null) {
                owner.setLabMemberName(memList.stream().filter(m -> m.getLabMemberId().equals(thisGroup.get(0).getLabMemberId())).findFirst().get().getUserName());
                owner.setCanUse(checkUserPower(user, LabMemberPowerEnum.reagent, thisGroup.get(0).getLabMemberId()) || thisGroup.get(0).getLabMemberId().equals(user.getLabMemberId()));
            } else {
                owner.setLabMemberName("公用");
                owner.setCanUse(true);
            }
            owner.setPanelRows(thisPanel.getRows());
            owner.setPanelColumns(thisPanel.getColumns());
            owner.setIsSingleBox(false);
            if (owner.getBoxId() != null) {
                Optional<Box> boxOpt = boxList.stream().filter(b -> b.getId().equals(owner.getBoxId())).findFirst();
                if (boxOpt.isPresent()) {
                    if (boxOpt.get().getRows() == 1 && boxOpt.get().getColumns() == 1) {
                        owner.setIsSingleBox(true);
                    }
                }
            }
            reagentInvList.add(owner);
            if (g.getKitBoxId() != null) {
                List<PanelGridUsed> panelGridUsedList = panelService.getPanelGridUsedListByBoxId(g.getKitBoxId(), BoxTypeEnum.KIT_BOX);
                owner.setGridUsedList(panelGridUsedList);
            }
            reagentIdCache.add(g.getReagentId());
        }
        specList.forEach(sp -> {
            if (!reagentIdCache.contains(sp.getReagentId())) {
                ReagentInventoryWithOwner owner = new ReagentInventoryWithOwner();
                Reagent thisRea = reagentList.stream().filter(r -> r.getId().equals(sp.getReagentId())).findFirst().get();
                owner.setZoneName(zoneMap.get(thisRea.getZone()));
                owner.setUnitName(unitMap.get(thisRea.getUnit()));
                owner.setReagentId(thisRea.getId());
                owner.setReagentName(thisRea.getName());
                owner.setUnit(thisRea.getUnit());
                owner.setZone(thisRea.getZone());
                owner.setClassify(thisRea.getClassify());
                owner.setGroupId(groupId);
                owner.setKitId(thisRea.getKitId());
                owner.setKitSpecId(sp.getId());
                owner.setKitType(kit.getKitType());
                owner.setReagentTypeId(thisRea.getReagentTypeId());
                owner.setLabId(thisRea.getLabId());
                owner.setFirstReagentTypeId(typeList.stream().filter(t->t.getId().equals(thisRea.getReagentTypeId())).findFirst().get().getParentId());
                reagentInvList.add(owner);
            }
        });
        return reagentInvList;
    }

    public List<KitInventory> getOneReagentKitInventory(Long kitId, UserInfoVo user) {
        Kit kit = kitService.selectById(kitId);
        Assert.isTrue(kit != null && kit.getLabId().equals(user.getLabId()), ResultEnum.DATA_NOT_EXIST.getMessage());
        List<ReagentInventory> invList = new ArrayList<>();
        invList = reagentInventoryService.getInventoryList(kit.getId(), null, null);
        if (invList.size() <= 0) {
            return new ArrayList<>();
        }
        List<Reagent> reagentList = reagentService.selectList(kit.getId());
        List<LabMemberVo> memList = labMemberService.selectList(user.getLabId(), null);
        List<Long> groupIdList = invList.stream().map(ReagentInventory::getGroupId).distinct().collect(Collectors.toList());
        List<Long> boxIdList = invList.stream().filter(i -> i.getBoxId() != null).map(ReagentInventory::getBoxId).distinct().collect(Collectors.toList());
        List<Box> boxList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(boxIdList)) {
            boxList = boxService.listByIdList(boxIdList);
        }
        List<KitInventory> voList = new ArrayList<>();
        List<KitSpec> specList = kitSpecService.getKitSpecListBySpecId(invList.get(0).getKitSpecId());
        Assert.isTrue(specList.size() == 1, ResultEnum.REQUEST_PARAM_ERROR.getMessage());
        Map<Integer, String> unitMap = dictService.getUnitMap();
        Map<Integer, String> zoneMap = dictService.getZoneMap();
        Map<Long, Panel> panelCache = new HashMap<>();
        List<ReagentType> typeList = reagentTypeService.selectLabReagentTypeList(user.getLabId());
        for (Long o : groupIdList) {
            KitInventory kitInventory = new KitInventory();
            List<ReagentInventory> thisGroup = invList.stream().filter(inv -> inv.getGroupId().equals(o)).collect(Collectors.toList());
            kitInventory.setKitId(kit.getId());
            kitInventory.setName(kit.getName());
            kitInventory.setReagentCount(reagentList.size());
            kitInventory.setKitType(kit.getKitType());
            kitInventory.setKitUnitName(unitMap.get(kit.getUnit()));
            kitInventory.setKitUnit(kit.getUnit());
            if (thisGroup.get(0).getLabMemberId() != null) {
                kitInventory.setLabMemberName(memList.stream().filter(m -> m.getLabMemberId().equals(thisGroup.get(0).getLabMemberId())).findFirst().get().getUserName());
                kitInventory.setCanUse(checkUserPower(user, LabMemberPowerEnum.reagent, thisGroup.get(0).getLabMemberId()) || thisGroup.get(0).getLabMemberId().equals(user.getLabMemberId()));
            } else {
                kitInventory.setLabMemberName("公用");
                kitInventory.setCanUse(true);
            }
            kitInventory.setAmount(getOneGroupKitAmount(kit.getId(), o, user, specList, invList));
            kitInventory.setBatchNumber(invList.get(0).getBatchNumber());
            kitInventory.setExpireDate(invList.get(0).getExpireDate());
            kitInventory.setProduceDate(invList.get(0).getProduceDate());
            kitInventory.setGroupId(o);
            kitInventory.setLabMemberId(thisGroup.get(0).getLabMemberId());
            kitInventory.setAllIn(specList.size() == thisGroup.stream().map(ReagentInventory::getReagentId).distinct().count());
            List<ReagentInventoryWithOwner> reagentInvList = new ArrayList<>();
            kitInventory.setReagentInventoryWithOwnerList(reagentInvList);
            Set<Long> reagentIdCache = new HashSet<>();
            for (ReagentInventory g : thisGroup) {
                Panel thisPanel = panelCache.get(g.getPanelId());
                if (thisPanel == null) {
                    thisPanel = panelService.get(g.getPanelId());
                    panelCache.put(thisPanel.getId(), thisPanel);
                }
                ReagentInventoryWithOwner owner = new ReagentInventoryWithOwner();
                MyBeanUtils.copyProperties(g, owner);
                owner.setUnitName(unitMap.get(owner.getUnit()));
                owner.setZoneName(zoneMap.get(thisPanel.getZone()));
                owner.setLabMemberName(kitInventory.getLabMemberName());
                owner.setPanelRows(thisPanel.getRows());
                owner.setPanelColumns(thisPanel.getColumns());
                owner.setIsSingleBox(false);
                owner.setFirstReagentTypeId(typeList.stream().filter(t->t.getId().equals(owner.getReagentTypeId())).findFirst().get().getParentId());
                if (owner.getBoxId() != null) {
                    Optional<Box> boxOpt = boxList.stream().filter(b -> b.getId().equals(owner.getBoxId())).findFirst();
                    if (boxOpt.isPresent()) {
                        if (boxOpt.get().getRows() == 1 && boxOpt.get().getColumns() == 1) {
                            owner.setIsSingleBox(true);
                        }
                    }
                }
                owner.setCanUse(kitInventory.getCanUse());
                reagentInvList.add(owner);
                if (g.getKitBoxId() != null) {
                    List<PanelGridUsed> panelGridUsedList = panelService.getPanelGridUsedListByBoxId(g.getKitBoxId(), BoxTypeEnum.KIT_BOX);
                    owner.setGridUsedList(panelGridUsedList);
                }
                reagentIdCache.add(g.getReagentId());
            }
            specList.forEach(sp -> {
                if (!reagentIdCache.contains(sp.getReagentId())) {
                    ReagentInventoryWithOwner owner = new ReagentInventoryWithOwner();
                    Reagent thisRea = reagentList.stream().filter(r -> r.getId().equals(sp.getReagentId())).findFirst().get();
                    owner.setZoneName(zoneMap.get(thisRea.getZone()));
                    owner.setUnitName(unitMap.get(thisRea.getUnit()));
                    owner.setReagentId(thisRea.getId());
                    owner.setReagentName(thisRea.getName());
                    owner.setUnit(thisRea.getUnit());
                    owner.setZone(thisRea.getZone());
                    owner.setClassify(thisRea.getClassify());
                    owner.setGroupId(o);
                    owner.setKitId(thisRea.getKitId());
                    owner.setKitSpecId(sp.getId());
                    owner.setKitType(kit.getKitType());
                    owner.setReagentTypeId(thisRea.getReagentTypeId());
                    owner.setLabId(thisRea.getLabId());
                    owner.setFirstReagentTypeId(typeList.stream().filter(t->t.getId().equals(owner.getReagentTypeId())).findFirst().get().getParentId());
                    reagentInvList.add(owner);
                }
            });
            voList.add(kitInventory);
        }
//        inventoryRecordService.add(user, kit.getId(), InventoryRecordEnum.SEE);
        return voList;
    }
}
